这个互操作C#/托管/非托管C ++参数传递有什么问题?

时间:2014-06-13 23:31:03

标签: c# c++ dll interop

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

我也不认为我已经正确设置了回调,但我还没有能够测试它的地方。有什么想法吗?

1 个答案:

答案 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");

希望这可以帮助你或某人。