Search code examples
c#c++dllimportdllexport

Export a C++ DLL function and import into C#


So I am trying to export a function in a DLL that was developed in C++ into a C# project. After digging around online and doing some book research as well I found a means to do so. However my exposure to this is limited and all my knowledge is self taut so I am sure that I messed something up somewhere.

I am exporting the function like so:

STDMETHODIMP __export DataSetpImpl::set_HeaderFile(BSTR Value)

and importing it as such:

public unsafe class test
{
  const string _dllLocation = "DllPath.dll";
  [DLLImport(_dllLocation, CallingConvention = CallingConvention.stdCall)]
  [return: MarshalAs(UnmanagedType.Bstr)]
  public static extern string set_HeaderFile([MarshalAs(UnmanagedType.BStr)] String path);
}

then call it in the application as followes:

test.set_HeaderFile(@"C:\temp\SomeHeaderFile.hdz");

everything builds correctly and links up just fine... the issue appears when the application hits the above call. It throws and error saying:

Unable to find an entry point named 'set_HeaderFile' in DLL 'DLLPath.dll'.

any ideas on what I am doing wrong? Also please keep in mind my knowledge on this subject if very limited, I am just going off what I could find online and in notes around the office.


Solution

  • This way you can only import non-class member functions.

    The name "set_HeaderFile" in your case is mangled into something like "DataTableImpl$$set_HeaderFile@4" and even if it is declared as static, the CLR won't find this in your .dll file using the name "set_HeaderFile".

    You can make a workaround.

    Say you have a

    DataSetpImpl* g_Instance;
    

    Then write a function

    LONG __stdcall mySetHeaderFile(BSTR Val)
    {
        return g_Instance->set_HeaderFile(Val);
    }
    

    and then in C# you can access it.

    [DLLImport(_dllLocation, CallingConvention = CallingConvention.stdCall, EntryPoint="mySetHeaderFile")]
    public static extern Int32 set_HeaderFile([MarshalAs(UnmanagedType.BStr)] String path);
    

    Returning BSTRs also require some wrapping using the Marshalling. See this: http://msdn.microsoft.com/en-us/library/7b620dhe.aspx