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

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

本文关键字:导入 C++ DLL 函数 导出      更新时间:2023-10-16

所以我正在尝试将 DLL 中C++开发的函数导出到 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:tempSomeHeaderFile.hdz");

一切都正确构建并且链接得很好......当应用程序命中上述调用时,会出现此问题。 它抛出并错误地说:

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

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

这样,您只能导入非类成员函数。

在您的案例中,名称"set_HeaderFile"被修改为类似于"DataTableImpl$$set_HeaderFile@4"的内容,即使它被声明为静态,CLR 也不会在.dll文件中使用名称"set_HeaderFile"找到它。

您可以采取解决方法。

假设你有一个

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

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

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

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

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