Building Lua Modules for LuaInterface - c#

I have a Lua module (lpack) that I need to load into LuaInterface. I've tried a few different configurations for the project, but I can't seem to figure out the linking.
I get the error unresolved external symbol "void __stdcall lua_replace(struct lua_State *,int)" (?lua_replace##YGXPAUlua_State##H#Z) referenced in function "int __stdcall l_unpack(struct lua_State *)" (?l_unpack##YGHPAUlua_State###Z)
If I run dumpbin /exports on the lua51.lib file, I can find ?lua_replace##YAXPAUlua_State##H#Z which matches what I find in the lua51.dll with Dependency Walker ?lua_replace##YAXPAUlua_State##H#Z, so the function exists but the names don't match.
I'm not very familiar with this level of linker management, so this may be a simple error on my part. Why is the value in the lpack build not matching that of the lua51.lib input file?
Update
All of the exports in the lua51.dll and lua51.lib files were __cdecl and my lpack project has been set to __stdcall. Changing that property (under C/C++ -> Advanced -> Calling Convention) fixed the compile issue and I now have an lpack.dll file.
However, when I attempt to load the file from lua require('lpack') it fails with The specified procedure could not be found.
Breaking in the lua C code that loads the library with LoadLibraryA returns NULL and a GetLastError() code of 0x7F.
Update 2
The lpack.dll file I was attempting to load was out of date due to a wrong output directory, so that fixed the LoadLibrary failure. Next the GetProcAddress would fail, but if I added extern "C" to the export function in the lpack.c file as per Mud's recommendation, the problem was resolved.

However, when I attempt to load the file from lua require('lpack') it fails with The specified procedure could not be found.
Probably because the name is mangled. Did you look in the DLL to see the actual (mangled) name of the function?
You really ought to build the Lua source (and any Lua modules written in C) as C, and use extern "C" when importing them. Save you a lot of headaches.

Related

Using multiple DLL's written in C within a C# program

I have a program written in C#. I want to use a DLL made in C within this program.
public class Test
{
[DllImport(#"C:/.../surcouche2.dll")]
public static extern int refreshEntities();
}
I call the function as:
Test.refreshEntities();
I am using Visual Studio. To create the DLL surcouche2.dll, I created a new Visual C++ Application Console, then I chose DLL and left the options on their defaults. Then, I told to VS to compile using C.
The function is :
__declspec(dllexport) int refreshEntities() {
int ret = 0;
LibData *n;
n = newLibData(LIB_MODULES_MODULE_ENTITES, LIB_MODULES_ACTION_SELECT,
"http://10.0.2.2:4242/WebService1.asmx");
if (n)
{
ret = n->refreshDb(n);
n->destroy(n);
}
return (ret);
}
The functions called in are in another DLL (that is referenced). But I get this error:
system.DllNotFoundException: Impossible de charger la DLL 'C:/.../surcouche2.dll': Le module spécifié est introuvable. (Exception de HRESULT : 0x8007007E)
à app.Lol.refreshEntities()
à app.MainWindow..ctor() dans c:\...\MainWindow.xaml.cs:ligne 30
But, if I change the function refreshEntities like this, then it works fine:
__declspec(dllexport) int refreshEntities() {
return (42);
}
The second DLL uses another DLL (both in C). I created them with the option "create an empty project" so I haven't the stdafx.h, ... files. I guess it's not a problem because I can use a function from the third DLL in the second one.
This error can happen if a dependency of loaded dll can't be resolved.
First of all I propose you to put both native assemblies in a bin folder and change a reference
from [DllImport(#"C:/.../surcouche2.dll")] to [DllImport("surcouche2.dll")]
In general to debug dependency issues tools like Dependency Walker and Process Monitor can be useful. First helps to understand what the dependencies are, second to check there your application is trying to find the assemplies.
Configure Process Monitor's to show process activity only and apply process name filter with your application name like on the picture below and you will get all files your app trying to access. It will help to find missing dll's.
[DllImport(#"C:/.../surcouche2.dll")]
This is bad idea, you are getting a preview of what is going to go wrong on your user's machine as well. Hard-coding the path to the DLL like that helps the pinvoke marshaller to find the DLL file on disk. But it does absolutely nothing to help the operating system to find DLLs that surchouce2.dll needs. Like the one that contains the newLibData() function.
The error message is often mis-interpreted. It says it "cannot load" surcouche2.dll. Which is accurate, but most programmers will read the message as "cannot find" surcouche2.dll. The most common reason for the exception. Not the problem here.
Never mess with DLL Hell. The days that keeping DLLs in a separate directory and sharing them between different programs was useful are long, long gone. Always copy dependent DLLs into the same directory as the EXE that needs them. Makes it very easy on the operating system to find them. And avoids the considerable misery you'll have to deal with when it finds the wrong file.
Use Project + Add Existing Item and select the DLLs. Set their Copy Local property to True. If you don't like the clutter then use XCOPY in a post-build event.

Entry point not found in dynamically loaded dll

In my windows application i have to load a dll dynamically. I achived this by DllImport attribute. But when i execute the command in Developer Command Prompt for Visual Studio dumpbin /exports on a DLL only 5 functions listed. I can't see my required function .But i can aceess the method when static linking. Is there any way to access the required function dynamically.
You can only call functions in a DLL that are exported. If this is your DLL then you need to recompile it to export the functions that you need to call. If it is not your DLL, and the function is not exported, then you are out of luck.
You state in comments that the function can be called when you link to the DLL statically. That means that the function is exported. Its name is likely mangled or decorated so that you do not recognise it. Once you can work out what the mangled or decorated name is, you will be able to link to the function with runtime linking.
Another possibility is that the function is exported from a different DLL, or perhaps even defined in a static lib. Without more details we cannot give you anything much more definitive than this.

A procedure imported by {dll} could not be loaded

I have several Unmanaged C++ written lib files which I need to link to Managed C++ dll.
Then I need to invoke functions of this Managed C++ from C# application.
First step is OK - Managed C++ dll is created, I can see with ildasm that it exports functions I need. However when I try to call this function from my C#-written test app it says:
An unhandled exception of type 'System.IO.FileLoadException' occurred in Unknown Module.
A procedure imported by {MyManagedCPP.dll} could not be loaded.
This message goes from VS2010.
I made simple experiment - removed dependencies from all lib files in Managed C++ dll and rebuild it.
With this change it is OK - app starts, I can call functions of Managed C++ dll from C# test app.
Is it not possible by design to call managed c++ functions when dll has static linkage with lib files? Technical restriction? Or there is some workaround?
Thanks
You no doubt have an implicit dependency on a native DLL. It isn't clear from the question what DLL that might be. It could be msvcrxx.dll for example, a runtime support library for native C++ code. Which would be rather bad, you don't want to mix CRT versions. Such a missing DLL otherwise prevents the C++/CLI assembly from getting loaded, producing the FileLoadException.
If you have no idea what that DLL might be then you could use SysInternals' ProcMon utility. The trace will show you the program searching for the DLL and not finding it. If it is msvcrxx.dll then be sure to rebuild the .lib files using the same compiler version you used to build the C++/CLI assembly. If it is something else then make sure you copy that DLL to the build directory.

Wrapping a DLL - Understanding why Import Fails

Background
I have an embedded system which runs an application originally written in C++ and compiled in Visual Studio, which results in a single executable and more than 30 DLLs. These libraries cannot be browsed in VS Object Browser or other tools such as P/Invoke Interop Assistant.
Loading some of the DLLs in Dependency Walker shows that all of them are missing some dependencies deep in their dependency tree (cdfview.dll, dwmapi.dll, w32topl.dll, ...) but according to this question, that is likely not an issue.
I have some of the source code files, and all of the compiled DLLs. The application currently runs without issue, indicating there are no real dependency issues.
I am trying to call some library functions and eventually make a wrapper using C#, but am unable to successfully import and call even the simplest of functions. I always receive the following error:
Unable to load DLL 'dllName.dll': A dynamic link library (DLL)
initialization routine failed. (Exception from HRESULT: 0x8007045A)
Sample Code [EDITED]
From the C++ source code header file I have the following declarations:
#define OB_API __declspec(dllexport) __cdecl
typedef unsigned long DWORD; // From windef.h
typedef DWORD OBSTATUS;
OBSTATUS OB_API TestObj(void);
In the C++ source code file the following definition is given (which would seem to always return true):
BOOL WINAPI DllMain(HANDLE /* hModule */,
DWORD ul_reason_for_call,
LPVOID /* lpReserved */
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
In my C# application class, I add the following declaration:
[DllImport(#"dllName.dll", CallingConvention=CallingConvention.Cdecl)
public static extern ulong TestObj();
The DLL and C# application binary reside in the same directory.
Questions
From researching the error, it seems there is a large number of reasons this particular exception could be thrown and I was wondering how I could further troubleshoot this type of issue.
Is there any way to get more detailed information on why the initialization routine failed?
(Note: target system is running .NET framework 2.0)
The DLL you are loading contains a DllMain() function. That's pretty common, such a function initializes the state of the DLL. Windows makes sure that this function is called whenever the DLL gets loaded, it will happen automatically the first time you pinvoke a function exported by that DLL.
Problem is, that function returned FALSE to indicate that it could not properly initialize the DLL. That of course does not give a wholeheckofalot of information about why it returned FALSE. Windows can't do anything but generate error 1114, ERROR_DLL_INIT_FAILED. If the DLL itself doesn't output any diagnostic then you can't do anything but debug the code. Start with Project + Properties, Debug tab, tick the "Enable unmanaged code debugging" option.
Fingers crossed that you see a message in the Output window. Odds are not very good. If you don't have the source code for the DLL then you'll need the help of the vendor or author of the DLL. Give him a copy of a test project that fails like this.
Maybe the reason is need to install old Net Framework version like 2.0, 3.0, 3.5,....it's worked for me :D

Importing Function From Unmanaged DLL in C# Application

I need to import a function that I wrote in C++, and is now compiled into a DLL, into my C# application. Everything builds without errors or warnings, but when I step through the code the first function call into the DLL throws an Exception with a message of "Unable to find an entry point named 'CreateScanEngine" in DLL 'WMIQuery.dll'." The function is declared like so in my C# application:
internal static class WMIQuery
{
[DllImport("WMIQuery.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
internal static extern void CreateScanEngine();
}
Dependency Walker shows the function there in the DLL as such:
Ordinal: 1(0x0001)
Hint: 0(0x0000)
Function ^: void CreateScanEngine(void)
Entry Point: 0x00001860
Dependency Walker also shows these errors/warnings for the DLL:
Error: At least one required implicit or forwarded dependency was not found.
Warning: At least one delay-load dependency module was not found.
Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.
Will this make a difference? Also, I tried adding the DLL as a reference to the C# project, and I got this error:
A reference to [my DLL] could not be added. Please make sure that the file is accessible, and that it is a valid assembly or COM component.
Does anyone know what I'm doing wrong? Thanks.
Don't use Dependency Walker, it unmangles the exported name of the function and doesn't tell you the real export name. Note that it is smart enough to see that it takes no arguments and has no return value. It can only do this if it sees the name as decorated by the C++ compiler.
Use Dumpbin.exe /exports on the DLL to see the real name. It ought to be "?CreateScanEngine##YGXXZ", use the EntryPoint property in the [DllImport] attribute. You may also want to declare the function with extern "C" so this name mangling doesn't happen.
How are you declaring CreateScanEngine in your C++ code?
Try changing to:
extern "C" __declspec(dllexport) void __stdcall CreateScanEngine();

Categories

Resources