如何通过CLI/C++包装器从C#调用含byte*、int*参数的C++函数
解决C#通过CLI/C包装器调用含int*参数的C函数问题
首先要修正原生C++函数的逻辑错误:原IncrementBy2函数直接对指针地址做加法,并没有修改指针指向的实际数值,必须解引用指针后再操作。
1. 修复原生C++类代码
class UNMANAGEDLIB_API CUnmanagedLib { public: CUnmanagedLib(void); public: void PrintMessage(char* message) { CString StrMessage = message; MessageBox(NULL, StrMessage, L"Test Message", MB_OK); } public: void IncrementBy2(int* myval) { // 解引用指针,修改实际指向的数值 *myval += 2; } };
2. 修改CLI/C++包装器类
CLI包装器中不能直接用int*作为对外暴露的参数,应该使用CLI的跟踪引用int%,对应C#的ref关键字,这样无需启用unsafe模式就能安全传递引用:
#pragma once #include "..\UnmanagedLib\UnmanagedLib.h" using namespace System; using namespace System::Runtime::InteropServices; namespace NativeCodeWrapper { public ref class Class1 { public: void SendMessageWrapper(String^ strMessage) { CUnmanagedLib instance; char* str2 = (char*)(void*)Marshal::StringToHGlobalAnsi(strMessage); instance.PrintMessage(str2); // 释放Marshal分配的非托管内存,避免泄漏 Marshal::FreeHGlobal(IntPtr(str2)); } public: void IncrementBy2Wrapper(int% myval) { CUnmanagedLib instance; // 将跟踪引用转换为非托管指针传递给原生函数 int* valPtr = &myval; instance.IncrementBy2(valPtr); } }; }
注:原SendMessageWrapper存在内存泄漏,需添加Marshal::FreeHGlobal释放分配的内存。
3. C#调用代码修改
在C#中使用ref关键字传递参数,即可让原生函数修改C#变量的实际值:
NativeCodeWrapper.Class1 cls = new NativeCodeWrapper.Class1(); // 正常调用字符串参数的函数 cls.SendMessageWrapper("Hello"); int i = 0; // 使用ref关键字传递参数,让原生函数修改i的值 cls.IncrementBy2Wrapper(ref i); // 此时i的值会被修改为2 Console.WriteLine(i);
内容的提问来源于stack exchange,提问作者Jaz
相关产品推荐
相关产品推荐

