gpt4 book ai didi

c# - 如何使用正确的参数类型从 C# 正确调用 C++ DLL

转载 作者:行者123 更新时间:2023-11-30 04:06:42 28 4
gpt4 key购买 nike

我已经获得了一个 DLL,它将被 C# 等调用。 DLL包含如下两个方法

extern "C" {
__declspec(dllexport) BSTR GroupInit(LPCTSTR bstrIniFile, bool bDiagErr, bool bProcErr);
__declspec(dllexport) void G();
}

class GrouperServer {
public:
BSTR GroupInit(LPCTSTR bstrIniFile, bool bDiagErr, bool bProcErr);
void G();
}

BSTR GrouperServer::GroupInit(LPCTSTR bstrIniFile, bool bDiagErr, bool bProcErr) {
CString strResult = "";
char* sz;
SetVars(bDiagErr, bProcErr);

if (sz = ::GroupInit((char*)bstrIniFile, 1))
strResult = sz;
return strResult.AllocSysString();
}

void G() {
MessageBox(0, "And text here", "MessageBox caption", MB_OK);
}

我试图通过首先定义类从 C# 调用这些 DLL:

public class GrouperServer {
[DllImport("GrouperServer.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void G();

[DllImport("GrouperServer.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern string GroupInit(
string strCmdFile, bool bAllowBadDiagCodes, bool bAllowBadProcCodes);
}

和做

this.strCommandFilePath = "C:\\MyDir\\MyCommandFile.txt";
Grouper.GrouperServer.G();
Grouper.GrouperServer.GroupInit(this.strCommandFilePath, true, true);

调用方法 G()有效,我收到一个消息框,但用于调用 GroupInit() , 我得到

An unhandled exception of type 'System.EntryPointNotFoundException' occurred in DrGroupIN.exe. Additional information: Unable to find an entry point named 'GroupInit' in DLL 'GrouperServer.dll'.

如何调用第二种方法GrouInit(...)在这种情况下使用正确的参数?


编辑 1.

我也试过

[DllImport("GrouperServer.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr GroupInit(
string strCmdFile, bool bAllowBadDiagCodes, bool bAllowBadProcCodes);

调用方式:

IntPtr ptr = Grouper.GrouperServer.GroupInit(this.strCommandFilePath, true, true);
string strString = Marshal.PtrToStringBSTR(ptr);
Marshal.FreeBSTR(ptr);

但这也会引发上述错误。

编辑 2.

我也试过

[DllImport("GrouperServer.dll", CallingConvention = CallingConvention.Cdecl, CharSet=CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern string GroupInit(
[MarshalAs(UnmanagedType.LPTStr)]string strCmdFile,
bool bAllowBadDiagCodes,
bool bAllowBadProcCodes);

但这也会引发上述错误。

最佳答案

在我看来,您似乎无法使用 C# 调用此 DLL。 DLL 导出类的成员函数。而且您无法实例化该类。

我可以看到以下选项:

  1. 要求 DLL 供应商导出静态成员函数或非成员函数。这些应该可以使用 p/invoke 访问。
  2. 围绕 DLL 编写混合模式 C++/CLI 包装器。此包装器可以轻松使用非托管 DLL。反过来,它可以公开包装功能的托管 ref 类。然后可以将 C++/CLI 包装器添加为对 C# 项目的引用。

也就是说,这些声明似乎有冲突:

extern "C" {
__declspec(dllexport) BSTR GroupInit(LPCTSTR bstrIniFile, bool bDiagErr, bool bProcErr);
__declspec(dllexport) void G();
}

class GrouperServer {
public:
BSTR GroupInit(LPCTSTR bstrIniFile, bool bDiagErr, bool bProcErr);
void G();
}

第一对声明似乎是非成员函数。但是它们后面跟着一个具有相同名称的成员函数的类。您确实需要清楚您尝试调用哪些函数。

也许 DLL 已经包含了非成员函数来包裹成员函数。在这种情况下,您只需要找出导出它们所用的名称。使用 Dependency Walker 来做到这一点。

那么,如何声明 p/invoke。您需要知道正在使用的字符集,以及导出函数的名称。让我们假设 Unicode。 p/invoke 将是:

[DllImport("GrouperServer.dll", CallingConvention = CallingConvention.Cdecl,
EntryPoint = "<exported name goes here>")]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern string GroupInit(
[MarshalAs(UnmanagedType.LPWStr)]
string strCmdFile,
bool bAllowBadDiagCodes,
bool bAllowBadProcCodes
);

关于c# - 如何使用正确的参数类型从 C# 正确调用 C++ DLL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22806973/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com