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++上下文中调用供应商库时,它可以完美地工作,并且已知该文件是好的。我想我在处理参数的方式上遗漏了一些明显的东西,但我看不出是什么。

我也不认为我有回调设置正确,但我不是点,我可以测试它。什么好主意吗?

c# /托管/非托管的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");

希望这对你或别人有帮助。