在 C# 中封送 IntPtr 数组

发布于 2024-08-28 13:02:24 字数 273 浏览 4 评论 0原文

我想从 C# 中的安全托管代码调用接收指针数组 (void**) 的 C API 中的函数。

我有相应的 IntPtr 对象托管数组,但 MSDN 文档中宣传的 Marshal 方法似乎不足以向具有正确内容的非托管内存块提供 IntPtr。

我本来希望通过“Marshal.AllocHGlobal”获得一个 IntPtr,然后使用“Marshal.Copy”分配正确的内容,但似乎该函数尚未针对 IntPtr 数组进行重载。

关于最好的方法有什么想法吗?

提前致谢。

From safe, managed code in C#, I would like to call a function in a C API that receives an array of pointers (void**).

I have the corresponding managed array of IntPtr objects, but the Marshal methods advertised in the documentation at MSDN do not seem sufficient to provide an IntPtr to an unmanaged block of memory with the correct content.

I had hoped to obtain an IntPtr with 'Marshal.AllocHGlobal' and then assign the correct content using 'Marshal.Copy', but it seems the function has not been overloaded for an array of IntPtr.

Any thoughts on the best way to do this?

Thanks in advance.

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

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

发布评论

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

评论(2

染墨丶若流云 2024-09-04 13:02:24

P/Invoke 编组器已完成此操作,您无需提供帮助。只需将函数参数声明为数组即可:

[DllImport("blah.dll")]
private static extern void SomeFunction(IntPtr[] array);

以防万一:虽然您不必在此处使用 unsafe 关键字,但它并不安全。当 C 代码写入超过您分配的块的末尾时,它很容易损坏堆。

The P/Invoke marshaller already does this, you don't have to help. Just declare the function argument as an array:

[DllImport("blah.dll")]
private static extern void SomeFunction(IntPtr[] array);

Just in case: although you don't have to use the unsafe keyword here, there isn't anything safe about it. The C code can easily corrupt the heap when it writes past the end of the block you allocated.

全部不再 2024-09-04 13:02:24

将数组作为 IntPtr[] 传递,IntPtr 默认情况下封送为 void*。不
需要不安全。

[DllImport("containingFoo.dll")]
public static extern void foo( IntPtr[] ptr);

...

// some floats
float[] fpa = {7.2F, 2.3F, 3.3F, 4.5F, 6.5F};
// allocate unmanaged for float[] fpa and int (length of array)
IntPtr fptr = Marshal.AllocHGlobal(fpa.Length *
Marshal.SizeOf(typeof(float)));
IntPtr iptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)));
// set length of array
Marshal.WriteInt32(iptr, fpa.Length);
// copy the array
Marshal.Copy(fpa, 0, fptr, fpa.Length);
// strore both pointers in IntPtr[]
IntPtr[] pptr = {fptr, iptr};
// call foo passing the IntPtr[] to C
foo(pptr);

//C/C++
// 注意,使用时stdcall是默认的调用约定
呼唤!!!

void __stdcall foo(void** data)
{
float * fa = (float*)*data; // first element points to float array
int *ip = (int*)data + 1; // pointer to next element in void array
int *pp = (int*)*ip; // get pointer to int
for (int i = 0; i < *pp ; i++)
{
printf("\t: %f\n", *fa++);
}
}

Pass the array as an IntPtr[], IntPtr are by default marshaled as void*. No
need for unsafe.

[DllImport("containingFoo.dll")]
public static extern void foo( IntPtr[] ptr);

...

// some floats
float[] fpa = {7.2F, 2.3F, 3.3F, 4.5F, 6.5F};
// allocate unmanaged for float[] fpa and int (length of array)
IntPtr fptr = Marshal.AllocHGlobal(fpa.Length *
Marshal.SizeOf(typeof(float)));
IntPtr iptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)));
// set length of array
Marshal.WriteInt32(iptr, fpa.Length);
// copy the array
Marshal.Copy(fpa, 0, fptr, fpa.Length);
// strore both pointers in IntPtr[]
IntPtr[] pptr = {fptr, iptr};
// call foo passing the IntPtr[] to C
foo(pptr);

//C/C++
// note that stdcall is the default calling convention when using
PInvoke!!!!

void __stdcall foo(void** data)
{
float * fa = (float*)*data; // first element points to float array
int *ip = (int*)data + 1; // pointer to next element in void array
int *pp = (int*)*ip; // get pointer to int
for (int i = 0; i < *pp ; i++)
{
printf("\t: %f\n", *fa++);
}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文