导出C ++ DLL函数并导入C#

时间:2012-06-29 14:40:32

标签: c# c++ dllimport dllexport

所以我试图将用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'.
关于我做错了什么的任何想法?另外请记住我对这个主题的了解,如果非常有限的话,我只是在网上和办公室的笔记中找到我想要的东西。

2 个答案:

答案 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。