将字节数组从 C++ 调用到 C#
pinvoke byte array from c++ to c#
我正在尝试将在 c++ 中创建的字节数组移动到 c# 以供使用,现在我发现该字节数组在 c++ 端有效,但当我返回 c# 时返回 null。
c++代码
__declspec(dllexport) void test(unsigned char* t_memory, int* t_size)
{
int width, height, channels_in_file;
t_memory = stbi_load("test.png", &width, &height, &channels_in_file, 0);
*t_size = width*height;
}
c#代码
[DllImport(DllFilePath, EntryPoint = "test", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
private static extern int _test(ref IntPtr memory, out int size);
public static void Test()
{
IntPtr memory = IntPtr.Zero;
_test(ref memory, out int size);
byte[] memoryArray = new byte[size];
Marshal.Copy(memory, memoryArray, 0, size);
Bitmap bmp;
using (var ms = new MemoryStream(memoryArray))
{
bmp = new Bitmap(ms);
}
bmp.Save("test_recreated.png");
}
试试下面的代码。一旦存在,方法 t_size 将不存在。所以必须在调用方法中分配内存。你的头像有多大。大小可能必须是 long 而不是 int。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string DllFilePath = @"c:\temp";
[DllImport(DllFilePath, EntryPoint = "test", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
private static extern int _test(ref IntPtr memory, ref IntPtr size);
static void Main(string[] args)
{
}
public static void Test()
{
IntPtr memory = IntPtr.Zero;
IntPtr _size = Marshal.AllocCoTaskMem(sizeof(int));
_test(ref memory, ref _size);
int size = (int)Marshal.PtrToStructure(_size, typeof(int));
byte[] memoryArray = new byte[size];
Marshal.Copy(memory, memoryArray, 0, size);
Bitmap bmp;
using (var ms = new MemoryStream(memoryArray))
{
bmp = new Bitmap(ms);
}
bmp.Save("test_recreated.png");
}
}
}
C++ 代码没有 return 数组,因为参数声明不正确。您传递了指针,但需要传递指针的地址。
C++ 代码应该像这样更改以匹配 C# 代码:
__declspec(dllexport) int test(unsigned char** t_memory, int* t_size)
{
int width, height, channels_in_file;
*t_memory = stbi_load("test.png", &width, &height, &channels_in_file, 0);
*t_size = width*height;
return 0;
}
您必须传递数组的地址,而不是数组本身。请注意此更改后与 size 参数设置的相似性。
我还包括一个 return 值以匹配 C# 代码。
您还需要导出一个释放器以避免泄漏此内存。
我正在尝试将在 c++ 中创建的字节数组移动到 c# 以供使用,现在我发现该字节数组在 c++ 端有效,但当我返回 c# 时返回 null。
c++代码
__declspec(dllexport) void test(unsigned char* t_memory, int* t_size)
{
int width, height, channels_in_file;
t_memory = stbi_load("test.png", &width, &height, &channels_in_file, 0);
*t_size = width*height;
}
c#代码
[DllImport(DllFilePath, EntryPoint = "test", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
private static extern int _test(ref IntPtr memory, out int size);
public static void Test()
{
IntPtr memory = IntPtr.Zero;
_test(ref memory, out int size);
byte[] memoryArray = new byte[size];
Marshal.Copy(memory, memoryArray, 0, size);
Bitmap bmp;
using (var ms = new MemoryStream(memoryArray))
{
bmp = new Bitmap(ms);
}
bmp.Save("test_recreated.png");
}
试试下面的代码。一旦存在,方法 t_size 将不存在。所以必须在调用方法中分配内存。你的头像有多大。大小可能必须是 long 而不是 int。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string DllFilePath = @"c:\temp";
[DllImport(DllFilePath, EntryPoint = "test", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
private static extern int _test(ref IntPtr memory, ref IntPtr size);
static void Main(string[] args)
{
}
public static void Test()
{
IntPtr memory = IntPtr.Zero;
IntPtr _size = Marshal.AllocCoTaskMem(sizeof(int));
_test(ref memory, ref _size);
int size = (int)Marshal.PtrToStructure(_size, typeof(int));
byte[] memoryArray = new byte[size];
Marshal.Copy(memory, memoryArray, 0, size);
Bitmap bmp;
using (var ms = new MemoryStream(memoryArray))
{
bmp = new Bitmap(ms);
}
bmp.Save("test_recreated.png");
}
}
}
C++ 代码没有 return 数组,因为参数声明不正确。您传递了指针,但需要传递指针的地址。
C++ 代码应该像这样更改以匹配 C# 代码:
__declspec(dllexport) int test(unsigned char** t_memory, int* t_size)
{
int width, height, channels_in_file;
*t_memory = stbi_load("test.png", &width, &height, &channels_in_file, 0);
*t_size = width*height;
return 0;
}
您必须传递数组的地址,而不是数组本身。请注意此更改后与 size 参数设置的相似性。
我还包括一个 return 值以匹配 C# 代码。
您还需要导出一个释放器以避免泄漏此内存。