c# /托管/非托管的c++参数传递有什么问题?
本文关键字:参数传递 什么 问题 c++ 托管 | 更新日期: 2023-09-27 18:08:38
我正在尝试通过c#访问非静态供应商c++ DLL。为了做到这一点,我正在编写一个托管c++包装器DLL,它基本上为供应商DLL创建静态变量,并使c#应用程序可以访问这些变量。
下面是一个例子:
typedef void(__stdcall *LPLISTENER_FUNC)(VENDORHANDLE hModule, VENDORWPARAM wParam, VENDORLPARAM lParam);
public delegate void VENDOR_Delegate(VENDORHANDLE hModule,
VENDORWPARAM wParam, VENDORLPARAM lParam);
public class VENDORWrapper
{
private:
static VENDORHSTORAGE _hStorage;
static VENDOR_Delegate^ _hOpenCallback;
void static Initialize()
{
_hStorage=storage_initialize();
}
void static registerCallback(unsigned int type, VENDOR_Delegate^ callback)
{
if (type == 2)
{
_hOpenCallback = callback;
::storage_register_callback(_hStorage, type, (LPLISTENER_FUNC)&_hOpenCallback);
}
}
bool static Open(String^ file)
{
bool retval=false;
filePath = file;
IntPtr ip = Marshal::StringToHGlobalAuto(filePath);
LPCWSTR str = static_cast<LPCWSTR>(ip.ToPointer());
//ERROR OCCURS HERE
retval = storage_open(_hStorage, str);
Marshal::FreeHGlobal( ip );
return retval;
}
void static Close()
{
storage_close(_hStorage);
}
}
c#是骨架:
public static VENDORStorageWrapper.VENDOR_Delegate openCallback
= new VENDORStorageWrapper.VENDOR_Delegate(fileOpened);
static void Main(string[] args)
{
VENDORStorageWrapper.VENDORStorageWrapper.Initialize();
Debug.WriteLine("DLL initalized");
VENDORStorageWrapper.VENDORStorageWrapper.registerCallback(2,
openCallback);
Debug.WriteLine("Callback registered");
VENDORStorageWrapper.VENDORStorageWrapper.Open("blah_file");
Debug.WriteLine("File opened");
}
public static void fileOpened(System.Int32 hstorage, System.UInt32 wParam, System.Int32 lParam)
{
Debug.WriteLine("file opened");
}
供应商DLL的函数被指定为__stdcall,所以我认为我在这方面是兼容的。供应商的initialize调用(上面的_storage_initialize)似乎正确地设置了句柄,它是静态作用域的。导致异常的storage_open调用接受一个VENDORHANDLE(真的很长)和一个LPCWSTR,我试图将从c#传递到的字符串转换为。我想这就是问题所在。
当运行时,应用抛出一个未处理的异常"System.Runtime.InteropServices. "上面注释行的SEHException"。异常来自供应商DLL内部,我没有源代码。当在非托管的c++上下文中调用供应商库时,它可以完美地工作,并且已知该文件是好的。我想我在处理参数的方式上遗漏了一些明显的东西,但我看不出是什么。
我也不认为我有回调设置正确,但我不是点,我可以测试它。什么好主意吗?
我不确定真正的大局,但根据我使用。net c#或vb的本机DLL的经验,为本机DLL创建一个简单的c#包装器(只是声明),而不是c++包装器。如果供应商的DLL真的是一个普通的DLL,就像大多数一样,这可能会有所帮助,就像Windows api调用一样。
namespace MyNameSpace
{
public class MyWrapper
{
// passing an int to the native DLL
[DllImport("Vendor.DLL")]
public static extern int DllFunc1(int hModule, int nData);
// passing a string to a native DLL expecting null terminated raw wide characters //
[DllImport("Vendor.DLL", CharSet=CharSet.Unicode )]
public static extern int Dllszset(int hModule, string text);
}
}
然后。net会为你处理它,你调用你的供应商函数…
MyNameSpace.MyWrapper.Dllszset(h, "hello");
希望这对你或别人有帮助。