在本机 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# 编组到本机 c++ 时,它会克隆吗?

从 c# 代码调用带有 void *parameter 的本机 c++ 函数

如何通过 IntPtr 将 c++ 数组编组为 c#

如何将 C++ 本机对象编组到托管 C++ CLI

在 C# 中将 CodeElements 编组到 IntPtr

将 C++ int* 编组为 C#