Exporting functions from C++ dll to C# P/Invoke

18,078

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).

Share:
18,078
Symmetric
Author by

Symmetric

Updated on June 04, 2022

Comments

  • Symmetric
    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
    Charlie about 15 years
    These are good ideas for isolating the real problem. You could also try adding a third function and seeing what happens with that one.
  • Symmetric
    Symmetric about 15 years
    In 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!