Exporting functions from C++ dll to C# P/Invoke
Solution 1
Are you using a .def file in your dll project to export those functions? If so, remove it and try again. This is just a guess because it looks like your exports are not what they should be when you do an extern "C" declspec(dllexports).
I tried this out with a simple C++ dll using
extern "C" __declspec(dllexport) BOOL Install();
extern "C" __declspec(dllexport) BOOL PPPConnect();
and a simple C# app using your PInvoke declarations and it worked fine.
When I did a dumpbin/exports on the dll I saw:
Dump of file PPPManager.dll
File Type: DLL
Section contains the following exports for PPPManager.dll
00000000 characteristics
499F6C2D time date stamp Fri Feb 20 20:51:25 2009
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 000110CD Install = @ILT+200(_Install)
2 1 00011069 PPPConnect = @ILT+100(_PPPConnect)
Notice that the exported names are different in my case.
Solution 2
It could be something as simple as PPPConnect
failing in a way that gets misinterpreted by the OS. Try implementing both Install
and PPPConnect
as no-ops (just have them return TRUE
without doing anything else) and see if the error persists. If so, try swapping the order in which they are exported (still as no-ops) and see if the problem is tied to ordering (unlikely) or to something else.
You can also use the graphical tool depends
to confirm what the DLL's exports table looks like, but I doubt the problem is coming from those quarters.
Solution 3
According to your description Install and PPPConnect differs only in names. I guess you simply use old .dll version with your C# application. A one without PPPConnect defined.
The declarations looks right (as far as I can judge without sources).
Symmetric
Updated on June 04, 2022Comments
-
Symmetric almost 2 years
I have built a C++ dll that I would like to call from C# code. I'm able to call one function, but the other throws an exception when the C# code tries to load the dll.
The header looks like this:
extern "C" __declspec(dllexport) BOOL Install(); extern "C" __declspec(dllexport) BOOL PPPConnect();
This produces a dll with slightly confusing exports table (what does foo = foo mean in the name field?):
File Type: DLL Section contains the following exports for PPPManager.dll 00000000 characteristics 499F44F0 time date stamp Fri Feb 20 16:04:00 2009 0.00 version 1 ordinal base 2 number of functions 2 number of names ordinal hint RVA name 1 0 000078E4 Install = Install 2 1 000079DC PPPConnect = PPPConnect
My P/Invoke declarations look like this:
[DllImport("PPPManager.dll")] private static extern bool Install(); [DllImport("PPPManager.dll")] private static extern bool PPPConnect();
The call to Install returns with no exception, but when I call PPPConnect, I get a MissingMethodException - "Can't find an Entry Point 'PPPConnect' in a PInvoke DLL 'PPPManager.dll'."
I've tried removing the extern and declspec directives from the Install function declaration, so that PPPConnect is the only function exported, and this still doesn't let me call PPPConnect.
I have also tried doing the DllImport by ordinal; this gives the same result as calling by name - Install returns, but PPPConnect throws the exception "Can't find an Entry Point '#2'...".
The interop log gives:
[pinvokeimpl][preservesig] bool invivodata.Common.System.IPAQUtils::Install(); BOOLEAN (I1_WINBOOL_VAL) Install(); JIT ERROR FOR PINVOKE METHOD (Managed -> Native): [pinvokeimpl][preservesig] bool invivodata.Common.System.IPAQUtils::PPPConnect(); BOOLEAN (I1_WINBOOL_VAL) PPPConnect();
This is well outside my area of expertise, so any suggestions or thoughts would be welcome.
Thanks, Paul
edit: It turns out that this code does work; the problem was with the latest dll not being propagated to the device. D'oh!
-
Charlie about 15 yearsThese are good ideas for isolating the real problem. You could also try adding a third function and seeing what happens with that one.
-
Symmetric about 15 yearsIn the end it turns out that I wasn't copying the latest dll over, due to my misunderstanding what the 'Add file to project' command in VS does. Your idea to try a stripped down dll was the seed I needed to go and figure that out. Thanks!