所以我试图将用C ++开发的DLL中的函数导出到C#项目中。在网上挖掘并做了一些书籍研究后,我发现了一种方法。然而,我对此的曝光是有限的,我所有的知识都是自我绷紧的,所以我确信我在某处搞砸了什么。
我正在导出这样的函数:
STDMETHODIMP __export DataSetpImpl::set_HeaderFile(BSTR Value)
并按原样导入:
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);
}
然后在应用程序中调用它,如下所示:
test.set_HeaderFile(@"C:\temp\SomeHeaderFile.hdz");
一切都正确构建并且链接得很好......当应用程序遇到上述调用时会出现问题。抛出错误说:
Unable to find an entry point named 'set_HeaderFile' in DLL 'DLLPath.dll'.
关于我做错了什么的任何想法?另外请记住我对这个主题的了解,如果非常有限的话,我只是在网上和办公室的笔记中找到我想要的东西。
答案 0 :(得分:2)
这样您就只能导入非类成员函数。
您的案例中的名称“set_HeaderFile”被修改为“DataTableImpl $$ set_HeaderFile @ 4”,即使它被声明为静态,CLR也不会使用名称“set_HeaderFile”在.dll文件中找到它”
您可以制定解决方法。
说你有
DataSetpImpl* g_Instance;
然后写一个函数
LONG __stdcall mySetHeaderFile(BSTR Val)
{
return g_Instance->set_HeaderFile(Val);
}
然后在C#中你可以访问它。
[DLLImport(_dllLocation, CallingConvention = CallingConvention.stdCall, EntryPoint="mySetHeaderFile")]
public static extern Int32 set_HeaderFile([MarshalAs(UnmanagedType.BStr)] String path);
返回BSTR还需要使用编组进行一些包装。请参阅:http://msdn.microsoft.com/en-us/library/7b620dhe.aspx
答案 1 :(得分:0)
我认为你混淆了两种与托管代码交互的方式。您可以将代码包装在COM服务器中,并利用.NET的COM互操作功能。或者你可以创建一个非类(即全局作用域)导出函数并使用P / Invoke。
该功能的措辞暗示COM。但是在C#方面,你错误地使用了P / Invoke。
我建议您使用P / Invoke。 COM是一个很大的话题;除非你愿意学习很多东西,否则不要去那里。
对于P / Invokable函数,创建一个非类函数。您不能通过P / Invoke从DLL中使用导出的C ++类。两个类系统 - 托管和C ++ - 非常不同。此外,您不必通过BSTR,P / Invoke可以使用良好的旧LPCWSTR。