1

所以我试图将用 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'.

关于我做错了什么的任何想法?如果我对这个主题的了解非常有限,请记住我的知识,我只是在网上和办公室周围的笔记中找到我能找到的东西。

4

2 回答 2

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 还需要使用 Marshalling 进行一些包装。看到这个:http: //msdn.microsoft.com/en-us/library/7b620dhe.aspx

于 2012-06-29T14:47:26.853 回答
0

我认为您混淆了与托管代码交互的两种方式。您可以将代码包装在 COM 服务器中并利用 .NET 的 COM 互操作工具。或者,您可以创建一个非类(即全局范围)导出函数并使用 P/Invoke。

该函数的措辞建议使用 COM。但是在 C# 方面,您错误地使用了 P/Invoke。

我建议你使用 P/Invoke。COM 是一个很大的话题;除非你愿意学习很多,否则不要去那里。

对于 P/Invokable 函数,创建一个非类函数。您不能通过 P/Invoke 使用从 DLL 导出的 C++ 类。两个类系统——托管和 C++——是完全不同的。此外,您不必传递 BSTR,P/Invoke 可以很好地用于旧的 LPCWSTR。

于 2012-06-29T14:47:52.267 回答