C# 从c向非托管cpp COM dll传递字节引用#

C# 从c向非托管cpp COM dll传递字节引用#,c#,c++,pointers,dll,reference,C#,C++,Pointers,Dll,Reference,谁能帮帮我吗。我使用的是一个C++的DLL,它被注册为我的C++项目(非托管C++ DLL)中的COM对象。我在C++中调用一个函数,它要求字节**作为一个参数(字节*是一个定义为char *的类型)。 DLL说明说明如下: [id(4),helpstring("Send packet via channel")] HRESULT SendPacket([in] struct FEG_UNIQUE_ID *Destination, [in,ref,size_is(MaxBytes),lengt

谁能帮帮我吗。我使用的是一个C++的DLL,它被注册为我的C++项目(非托管C++ DLL)中的COM对象。我在C++中调用一个函数,它要求字节**作为一个参数(字节*是一个定义为char *的类型)。 DLL说明说明如下:

[id(4),helpstring("Send packet via channel")] HRESULT  SendPacket([in] struct FEG_UNIQUE_ID *Destination, [in,ref,size_is(MaxBytes),length_is(MaxBytes)] BYTE *Data, [in] LONG MaxBytes, [out,retval] VARIANT_BOOL *Result);
public Boolean SendPacket(UInt64 destID, Byte[] data)
    {
        Byte [] temp = new Scrambler().scramble(data); //Scramble data to be sent

        byte[] nativeByte = new byte[temp.Length]; //Convert to native byte type

        for (int i = 0; i < temp.Length; i++)
            nativeByte[i] = (byte)temp[i]; 

        FEGClientModule.FEG_UNIQUE_ID UIdestID = new FEGClientModule.FEG_UNIQUE_ID();

        UIDHelper.SetIDLongLong(unchecked(destID), out UIdestID);

        bool result = feg.SendPacket(ref UIdestID, ref nativeByte[0], nativeByte.Length);

        return result;
    }
调用函数的c#代码执行以下操作:

[id(4),helpstring("Send packet via channel")] HRESULT  SendPacket([in] struct FEG_UNIQUE_ID *Destination, [in,ref,size_is(MaxBytes),length_is(MaxBytes)] BYTE *Data, [in] LONG MaxBytes, [out,retval] VARIANT_BOOL *Result);
public Boolean SendPacket(UInt64 destID, Byte[] data)
    {
        Byte [] temp = new Scrambler().scramble(data); //Scramble data to be sent

        byte[] nativeByte = new byte[temp.Length]; //Convert to native byte type

        for (int i = 0; i < temp.Length; i++)
            nativeByte[i] = (byte)temp[i]; 

        FEGClientModule.FEG_UNIQUE_ID UIdestID = new FEGClientModule.FEG_UNIQUE_ID();

        UIDHelper.SetIDLongLong(unchecked(destID), out UIdestID);

        bool result = feg.SendPacket(ref UIdestID, ref nativeByte[0], nativeByte.Length);

        return result;
    }
public Boolean SendPacket(UInt64 destID,字节[]数据)
{
Byte[]temp=new scramber().加扰(数据);//要发送的加扰数据
byte[]nativeByte=新字节[temp.Length];//转换为本机字节类型
对于(int i=0;i
我遇到的问题是,字节[](nativeByte)作为引用传递,但只有接收到的数组的第一个字节是正确的(我必须使用wireshark查看通过网络发送的数据)。接收客户端只是忽略数据包:(发送的剩余字节每次都不同

对象浏览器显示函数希望传递“ref byte”,我不知道我做错了什么,因为DLL在许多其他cpp项目中使用,没有任何问题。任何建议都将不胜感激:)

更新:

嗨,汉斯,谢谢你的帮助,我已经阅读了安全阵列声明。我试过这篇文章(见最后一个解决方案)。该论坛上的最后一篇文章给出了一个示例,说明了如何在不改变DLL项目的情况下更改il(但我遇到了相同的问题,尽管我没有使用代理/存根DLL)。然后,我尝试从存根/代理DLL生成互操作DLL并修改该il,但它给了我内存不足的异常。我还尝试将CPP DLL项目中的字节*声明为SAFEARRAY(字节),但它给了我一个语法错误


但是命运会让它注销所有DLL,清理等等。我回到了原来的DLL,现在我继续得到内存不足的异常。非常有趣的xD…将让您随时了解情况。

您的com对象方法使用指向字节的指针,但您传递的只是字节的第一项(nativeByte[0]),这是错误的,请像这样调用该方法

    bool result = feg.SendPacket(ref UIdestID, ref nativeByte, nativeByte.Length);

另外,您是否在intellisense中看到了当您键入feg.SendPacket时该方法所期望的参数,这将帮助您决定是否为参数添加ref关键字。

您的com对象方法采用指向字节的指针,但您传递的只是字节的第一项(nativeByte[0]),这是错误的,像这样调用方法

    bool result = feg.SendPacket(ref UIdestID, ref nativeByte, nativeByte.Length);

另外,您是否在intellisense中看到了当您键入feg.SendPacket时,该方法所期望的参数是什么,这将帮助您决定是否为参数添加ref关键字。

它不应该是
ref nativeByte
还是仅仅是
nativeByte
,而不是
ref nativeByte[0]
?另外,IDL函数原型中的
ref
属性也让我感到困惑。您的方法声明在类型库中没有很好地保存下来。这是因为您没有使用SAFEARRAY,即与自动化兼容的数组类型。幸存下来的是字节*,看起来像是通过引用传递给Tlbimp.exe的单个字节。修复它相当痛苦,您必须使用ildasm.exe反编译互操作库,编辑.il文件中的方法声明,并将humpty dumpty与ilasm.exe放回一起。使用从等效C#方法获得的IL来了解如何编辑.IL文件。它不应该是
ref-nativeByte
,甚至不应该是
nativeByte
,而不是
ref-nativeByte[0]
?另外,IDL函数原型中的
ref
属性也让我感到困惑。您的方法声明在类型库中没有很好地保存下来。这是因为您没有使用SAFEARRAY,即与自动化兼容的数组类型。幸存下来的是字节*,看起来像是通过引用传递给Tlbimp.exe的单个字节。修复它相当痛苦,您必须使用ildasm.exe反编译互操作库,编辑.il文件中的方法声明,并将humpty dumpty与ilasm.exe放回一起。使用从等效C#方法获得的IL来了解如何编辑.IL文件。我尝试了您的解决方案,但它只是给了我一个错误,说Byte[]无法转换为ref Byte:(我尝试了您的解决方案,但它只是给了我一个错误,说Byte[]无法转换为ref Byte:(