将struct *从C#传递到C ++ DLL [英] Pass struct* from c# to c++ dll

查看:186
本文介绍了将struct *从C#传递到C ++ DLL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

c ++ dll中的结构定义如下:

The struct in c++ dll is defined like this:

struct WAVE_INFO {
    int channel_num;
    int audio_type;
    char *wave_data;
    int wave_length;
};

和这样的调用方法:

extern "C" STRUCTDLL_API int processStruct(WAVE_INFO *pIn, WAVE_INFO *pOut);

我的c#结构中的 wave_data 必须为字节数组(byte [])****,而不是char []或字符串.我应该如何在调用dll的c#中定义结构和方法?而且wave_date的长度是固定的,比方说100.

The wave_data in my c# struct has to be byte array (byte[])****, not char[] or string. How should I defind the struct and the method in c# where the dll is called? And the length of wave_date is fixed, let's say like 100.

推荐答案

首先,我会说C ++结构的声明不正确.有效负载是二进制数据,因此该数组应为 unsigned char * ,而不是 char * .

First of all, I would say that the C++ struct is declared incorrectly. The payload is binary data so the array should be unsigned char* rather than char*.

撇开这一点,由于数组的原因,该结构有点不可思议了.它是这样的:

Leaving that aside, the struct is a little fiddly to marshal because of the array. It goes something like this:

[StructLayout(LayoutKind.Sequential)]
struct WAVE_INFO
{
    public int channel_num;
    public int audio_type;
    public IntPtr wave_data;
    public int wave_length;
}

我们无法在要编组的结构中使用 byte [] .相反,我们必须将数组声明为 IntPtr 并自行处理编组.最干净的方法是声明 byte [] 数组,并使用 GCHandle 固定它们.

We can't use byte[] in the struct to be marshalled. Instead we have to declare the array as IntPtr and handle the marshalling ourselves. The cleanest way is to declare byte[] arrays and pin them with GCHandle.

导入的函数如下:

[DllImport(dllfilename, CallingConvention = CallingConvention.Cdecl)]
static extern int processStruct(ref WAVE_INFO infoIn, ref WAVE_INFO infoOut);

对函数的相当混乱的调用是这样的:

And the rather messy call to the function goes like this:

var dataIn = new byte[256];
// populate the input data array
var dataOut = new byte[256];

GCHandle dataInHandle = GCHandle.Alloc(dataIn, GCHandleType.Pinned);
try
{
    GCHandle dataOutHandle = GCHandle.Alloc(dataOut, GCHandleType.Pinned);
    try
    {
        WAVE_INFO infoIn;
        infoIn.audio_type = 1;
        infoIn.channel_num = 2;
        infoIn.wave_data = dataInHandle.AddrOfPinnedObject();
        infoIn.wave_length = dataIn.Length;

        WAVE_INFO infoOut = new WAVE_INFO();
        infoOut.wave_data = dataOutHandle.AddrOfPinnedObject();
        infoOut.wave_length = dataOut.Length;

        int retval = processStruct(ref infoIn, ref infoOut);
        // dataOut should have been populated by processStruct
    }
    finally
    {
        dataOutHandle.Free();
    }
}
finally
{
    dataInHandle.Free();
}

我在这里的假设是第一个参数用于输入,第二个参数用于输出.但是调用者有责任为输出结构分配wave数据数组.

My assumption here is that the first parameter is used for input, and the second parameter for output. But that the onus is on the caller to allocate the wave data array for the output struct.

我还假定了调用约定,但是您必须检查C ++宏 STRUCTDLL_API 以确定真正的调用约定是什么.

I've also assumed a calling convention, but you'd have to inspect the C++ macro STRUCTDLL_API to determine what the true calling convention is.

这篇关于将struct *从C#传递到C ++ DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆