PInvoke - 如何编组“SomeType* []”?

发布于 2024-12-25 01:17:26 字数 920 浏览 0 评论 0原文

我有一个本机库,其中包含一些本机 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 %%
%]

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

  • 输入参数列表(即 prhs,在 matlab 端初始化)
  • 输出参数列表(即 plhs,全部初始化为零,但 目前,从我所做

的测试来看,它仅返回 plhsprhs 列表中的第一个 mxArray*

I have a native library with some native ntype in it and would like to p/invoke some functions in it.

I was able to marshal for:

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

But don't know how to do it for:

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

At least IntPtr[] did not worked.

Edit

The unmanaged function I'm trying to marshal with is:

extern mxArray* mclCreateSimpleFunctionHandle(mxFunctionPtr fcn);

where mxFunctionPtr is:

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

This represent a call to the following matlab function signature:

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

Obviously, from my expectations, this function pointer should provide me with 2 lists of mxArray*:

  • The list of input arguments (i.e. prhs, initialized on matlab's side)
  • The list of output arguments (i.e. plhs, all initialized to zero but in which I should write into)

Currently from the tests I've made, it only returns for firsts mxArray* in plhs and prhs lists

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦幻的心爱 2025-01-01 01:17:26

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

First thing to do is to translate your native ntype into a managed struct.

For instance:

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

Then you define your method with a simple IntPtr parameter in your C# code.

[DllImport]
static void foo1(IntPtr myParam);

Finally here's how you use it:

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);
    }
}
二智少女 2025-01-01 01:17:26

明白了

'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);

Explanation

MarshalAs 属性指示编组SomeTime*[] 作为 IntPtrLPArray,其中数组的大小包含在从零开始的索引处的函数参数中尺寸参数索引

Got it

The correct marshalling for 'SomeTime* []' in:

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

is:

// 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);

Explanation

MarshalAs attribute indicates to marshal SomeTime*[] as a LPArray of IntPtr, where the size of the array is contained by function's parameter at the zero-based index SizeParamIndex

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文