在结构和指针上使用P / Invoke

时间:2013-07-09 14:11:56

标签: c# api pinvoke dllimport

我正在尝试使用P / Invoke调用第三方本机DLL中的某些函数。 但我一直收到FatalExecutionEngine错误。 可能我在编组数据时犯了一些错误或者?

这是我正在尝试使用的本机功能:

__declspec(dllexport) void dw_mm_directional_spectrum_initialise(
    struct dw_mm_directional_spectrum_T* directional_spectrum
    , const enum dw_buoy_type_T buoy_type
    , const unsigned char status[ /* NULL || sample_count */ ]
    , const double v[ /* sample_count */ ]
    , const double n[ /* sample_count */ ]
    , const double w[ /* sample_count */ ]
    , const unsigned int sample_count);

这是通过指针返回的本机结构:

struct dw_mm_directional_spectrum_T{
    signed char error_code;
    double* c_vv;
    double* c_nn;
    double* c_ww;
    double* c_nw;
    double* q_vn;
    double* q_vw;
    unsigned short output_size;
    double fraction_of_segments_used;
    unsigned char* list_of_used_segments;
    unsigned short list_of_used_segments_size;
};

这是C#程序中的结构定义:

[StructLayout(LayoutKind.Sequential)]
struct datawell{
    Byte error_code;
    double[] c_vv;
    double[] c_nn;
    double[] c_ww;
    double[] c_nw;
    double[] q_vn;
    double[] q_vw;
    ushort output_size;
    double fraction_of_segments_used;
    IntPtr list_of_used_segments;
    ushort list_of_used_segments_size;
};

我的DLLimport签名:

[DllImport("libwaves.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void dw_mm_directional_spectrum_initialise(
    out datawell dw,
    Byte buoy_type,
    Byte[] status,
    double[] v,
    double[] n,
    double[] w,
    ushort sample_count);

这就是我在C#程序中使用该函数的方法:

double[] vertical = new double[512]; 
double[] north = new double[512];
double[] west = new double[512];
Byte[] status = new Byte[512];
datawell dw_test = new datawell();
ushort cnt = 512;

//dummy data generation
for(int i=0;i<512;i++){
    status[i]=1;
    vertical[i]=i*1.0;
    north[i]=i*1.0;
    west[i]=i*1.0;
}

dw_mm_directional_spectrum_initialise(out dw_test,0,status, vertical, north,west,cnt);

任何帮助都将受到高度赞赏。

此致

Zjerre

2 个答案:

答案 0 :(得分:2)

您不能将结构中包含的指针编组为C#数组。您需要将它们声明为IntPtr,然后自己编组。您需要Marshal.Copy()来完成该过程。

我不确定内存所有权规则。据推测,本机代码会分配返回结构中的数组?如果是这样,那么我猜你在完成结构时必须再次调用本机库,以便它可以解除分配数组。

答案 1 :(得分:1)

list_of_used_segments在C中定义为unsigned char*,在C#中定义为double[]