我试图通过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,所以我认为我在这方面是合规的。供应商的初始化调用(上面的_storage_initialize)似乎正在设置句柄,这是静态范围的。导致异常的storage_open调用接受VENDORHANDLE(实际上很长)和LPCWSTR,我试图将从C#传递的字符串转换为。我认为这就是问题所在......
运行时,应用程序抛出未处理的异常&#34; System.Runtime.InteropServices.SEHException&#34;在上面的注释行。来自供应商DLL的例外,我没有源代码。当在非托管C ++上下文中调用时,供应商库可以很好地工作,并且该文件已知是好的。我想我在处理参数方面遗漏了一些明显的东西,但我看不出它是什么。
我也不认为我已经正确设置了回调,但我还没有能够测试它的地方。有什么想法吗?
答案 0 :(得分:0)
我不确定真正的大局,但我使用.net c#或vb的本机DLL的经验,为本机DLL而不是c ++包装器创建了一个简单的c#包装器(只是声明)。如果供应商DLL真的是一个vanilla 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");
希望这可以帮助你或某人。