PInvoke-如何封送';SomeType*[]';

本文关键字:SomeType PInvoke- 何封送 | 更新日期: 2023-09-27 18:19:26

我有一个本机库,里面有一些本机ntype,我想p/调用其中的一些函数。

我能够为进行编组

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 %%
%]

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

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

目前,从我所做的测试来看,它只在plhsprhs中返回第一个mxArray*,列出

PInvoke-如何封送';SomeType*[]';

首先要做的是将本机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);
    }
}

得到它

中"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*[]封送为IntPtrLPArray,其中数组的大小由函数的参数包含在从零开始的索引SizeParamIndex