PInvoke - 如何编组'SomeType * []'?

时间:2012-01-05 11:40:23

标签: c# pinvoke

我有一个本地库,其中包含一些原生ntype,并希望在其中调用一些函数。

我能够为:

编组
foo1(ntype** p) ==> foo1(IntPtr[] p)

但不知道如何做到:

foo1(ntype*[] p) ==> foo1(<???> p)

至少IntPtr[]没有效果。

修改

我试图编组的非托管函数是:

extern mxArray* mclCreateSimpleFunctionHandle(mxFunctionPtr fcn);

其中mxFunctionPtr是:

typedef void(*mxFunctionPtr)(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]);

这表示对以下matlab函数签名的调用:

function [varargout] = callback(varargins)
%[
    %% Do callback code %%
%]

显然,根据我的期望,这个函数指针应该为我提供2个mxArray*列表:

  • 输入参数列表(即prhs,在matlab上初始化)
  • 输出参数列表(即plhs,全部初始化为零,但我应该写入)

目前,根据我所做的测试,它只返回mxArray*plhs列表中的第一个prhs

2 个答案:

答案 0 :(得分:2)

要做的第一件事就是将您的原始ntype翻译为托管struct

例如:

public struct Ntype
{
    public int Field1;
    public long Field2;
}

然后,在C#代码中使用简单的IntPtr参数定义方法。

[DllImport]
static void foo1(IntPtr myParam);

最后,您将如何使用它:

IntPtr buffer = IntPtr.Zero;

try
{
    // Allocates a buffer. The size must be known
    buffer = Marshal.AllocHGlobal(0x1000);

    // Call to your unmanaged method that fills the buffer
    foo1(buffer);

    // Casting the unmanaged memory to managed structure that represents
    // your data
    Ntype obj = (Ntype)Marshal.PtrToStructure(buffer, typeof(Ntype));
}
finally
{
    // Free unmanaged memory
    if (buffer != IntPtr.Zero)
    {
        Marshal.FreeHGlobal(buffer);
    }
}

答案 1 :(得分:2)

明白了

正确编组“SomeTime* []”:

extern mxArray* mclCreateSimpleFunctionHandle(mxFunctionPtr fcn);
typedef void(*mxFunctionPtr)(int nlhs, mxArray* plhs[], int nrhs, mxArray* prhs[]);

是:

// For function pointer
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public delegate void MCRInteropDelegate(int nlhs,
                                        [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 0)][Out] IntPtr[] plhs, 
                                        int nrhs,
                                        [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 2)][In] IntPtr[] prhs);

// For API function
[DllImport(DLLNAME, EntryPoint = "mclCreateSimpleFunctionHandle", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
private static extern IntPtr _mclCreateSimpleFunctionHandle(MCRInteropDelegate fctn);

<强>解释

MarshalAs属性指示将SomeTime*[]编组为LPArray IntPtr,其中数组的大小由函数的参数包含在从零开始的索引{{} 1}}