C# PInvoke 传递出 unsigned char*

Posted

技术标签:

【中文标题】C# PInvoke 传递出 unsigned char*【英文标题】:C# PInvoke pass out unsigned char* 【发布时间】:2018-11-08 14:42:33 【问题描述】:

我正在尝试在 C++ 中创建一个简单的 dll,并使用 PInvoke 从 C# 调用它。我想传入一个字节数组,对其进行一些操作,然后发回另一个字节数组。我想我会传入框架和大小,然后创建一个非托管 unsigned char*。我会把它传回一个 out IntPtr 并返回大小。然后稍后我会用另一个函数释放那个内存。一切正常,除了我无法让 out IntPtr 工作。我总是得到0回来。我在 qt 中创建了我的 C++ dll。这是我到目前为止的代码。

#pragma once

#ifdef TOOLS_EXPORTS
#define TOOLS_API __declspec(dllexport)
#else
#define TOOLS_API __declspec(dllimport)
#endif

class Tools

public:
    int TOOLS_API TestFunction(const unsigned char *inData, int inSize, unsigned char *outData);
;

#include "Tools.h"

int Tools::TestFunction(const unsigned char *inData, int inSize, unsigned char* outData)

    outData = (unsigned char*)malloc(sizeof(unsigned char) * inSize);

    memcpy(outData, inData, sizeof(unsigned char) * inSize);

    return inSize;


[DllImport("Tools.dll", EntryPoint = "?TestFunction@Tools@@QAEHPBEHPAE@Z", CallingConvention = CallingConvention.StdCall)]
public static extern int TestFunction(byte[] inData, int inSize, out IntPtr outData);

IntPtr outData;

int test = TestFunction(data, data.Length, out outData);

【问题讨论】:

outData = (unsigned char*)malloc(sizeof(unsigned char) * inSize); 在这里不起作用,原因与从 C++ 调用该函数不起作用的原因相同,您正在重新分配指针的本地副本 【参考方案1】:

你的最终参数为:

unsigned char* outData

这是一个指针,按值传递。调用者看不到对地址的任何修改,因为地址是按值传递的。

你需要将你分配的内存地址返回给调用者。所以你需要:

unsigned char** outData

然后在您的 C++ 代码中实现该函数时,您将引用 outData 替换为 *outData

根据定义sizeof(unsigned char) == 1,将sizeof(unsigned char) * inSize 替换为inSize 是惯用的。

【讨论】:

捂脸时刻。完全有道理。在实际返回指针后,我正在使用 Marshal.Copy(outData, dest, 0, len) 并且它工作得很好。然后我应该能够将这个指针传回并让 C++ 释放非托管内存。 如果你使用LocalAlloc分配内存,那么你可以使用Marshal.FreeHGlobal销毁它。

以上是关于C# PInvoke 传递出 unsigned char*的主要内容,如果未能解决你的问题,请参考以下文章

将字符串从 C++ 传递到 C#

通过 Pinvoke 传递 C# 字符串

如何将带有 unsigned char* 的结构从 C# 传递到 C++?

从 C# 调用 C 函数,传递包含指针的结构

如何使用 pinvoke 将图像从 c 或 c++ 发送到 C#

__vectorcall 通过 C++/CLI 或 PInvoke (C#)