在本机 C++ 中将变量从 C# 编组为 void*,并在本机程序内更改 Managed/C# 中的变量值
Posted
技术标签:
【中文标题】在本机 C++ 中将变量从 C# 编组为 void*,并在本机程序内更改 Managed/C# 中的变量值【英文标题】:Marshal a variable from C# to void* in native C++ and change the variable value in Managed/C# inside native program 【发布时间】:2021-01-28 08:37:03 【问题描述】:我有这个 C++ 代码:
void ReleaseHandle(void* handle)
Machine.motor motor =static_cast<Machine.IMotor*> (handle)
if (motor == 0) throw;
delete motor;
handle = nullptr;
到目前为止,我可以在使用 uint 作为数据类型的托管中使用 PInvoke 将变量传递到 Releasehandle,问题是传递的变量的值不会改变。这个方法不是整个包,但我认为这足以说明我想要做什么。我需要更改该值,因为如果托管端的指针没有更改并且我决定再次从托管端调用 releaseHandle,它将抛出堆栈跟踪,因为调用了 releaseHandle 并且找不到(释放)机器。
我尝试了很多将数据类型作为 ref 从托管传递的方法,包括但不限于:
无效* [输入、输出] 无效* 单位 参考/输出单位 参考/输出无效* UintPtr 引用/输出 UintPtr我希望当我在托管中调用 ReleaseHandle 时
uint managedHandle = 123213124;
ReleaseHandle(managedHandle);
Console.WriteLine(managedHandle); // this outputs to 0
感谢您的帮助。
【问题讨论】:
如果你能描述你正在尝试做什么,这可能会有所帮助。 IE。为什么要更改指针值? 这不是“C/C++”代码(不存在这样的语言),而是 C++ 代码。删除 C 标签。 您需要像这样写ReleaseHandle()
:void ReleaseHandle(void** handle) *handle = nullptr;
- 注意使用“指针对指针”**
。您还必须相应地更新 P/Invoke 声明,可能使用ref IntPtr handle
。
你想做的C++端的操作是相当没用的。你并没有真正释放内存。如果你只是想重置一个指针,你可以在 C# 端进行。
nullptr 为零,所以在调用方法后您不会总是得到零吗?
【参考方案1】:
您的基本问题是,您打算更改按值传递的 a 变量。
话虽如此,正如Matthew Watson 在对您的问题的评论中指出的那样,您必须调整您在 DLL 中调用的方法的接口,以获取指向您要修改的指针位置的指针.
在您的示例中,您需要将指向managedHandle
的指针传递给ReleaseHandle
。
因此您的代码在 DLL 中应该如下所示:
void ReleaseHandle(void** handle)
*handle = nullptr; /* Note that here we dereference one level
to modify the content of the location
pointed at */
另一方面,在您的 C# 程序中,您应该使用类似的方式导入函数:
[DllImport("YourLibrary.dll")]
static extern void ReleaseHandle(ref IntPtr handle);
并使用 ref
关键字调用它:
IntPtr value = IntPtr.Add(IntPtr.Zero, 123456789);
ReleaseHandle(ref managedHandle);
Console.WriteLine(managedHandle); // this outputs to 0
【讨论】:
以上是关于在本机 C++ 中将变量从 C# 编组为 void*,并在本机程序内更改 Managed/C# 中的变量值的主要内容,如果未能解决你的问题,请参考以下文章
从 c# 代码调用带有 void *parameter 的本机 c++ 函数