简体   繁体   中英

Marshal a variable from C# to void* in native C++ and change the variable value in Managed/C# inside native program

I have this C++ code:

void ReleaseHandle(void* handle){
  Machine.motor motor =static_cast<Machine.IMotor*> (handle)
  if (motor == 0) throw;
  delete motor;
  handle = nullptr;
}

so far I can pass a variable into Releasehandle using PInvoke in Managed using uint as data type, problem is the value of passed variable doesn't change. This method is not the whole package, but i think this is enough to illustrate what i want to do. I need the value to change since if the pointer doesn't change in managed side and i decide to call releaseHandle again from managed, it will throw stacktrace since the releaseHandle is called and machine is not found (released).

I have tried a lot of methods of passing datatype as ref from managed including but not limited to:

  • void*
  • [In, Out] void*
  • uint
  • ref/out uint
  • ref/out void*
  • UintPtr
  • ref/out UintPtr

I expect when i call ReleaseHandle in managed like

uint managedHandle = 123213124;
ReleaseHandle(managedHandle);
Console.WriteLine(managedHandle); // this outputs to 0

Thank you for your help.

Your basic problem is, that you are intending to change the a variable you pass by value.

That having said, as Matthew Watson pointed out in the comment to your question, you have to adjust the interface of the method you are calling in the DLL to take a pointer pointing to the location of the pointer you want to modify.

In your example you need to pass the pointer to managedHandle to ReleaseHandle .

Hence your code should look like this in your DLL:

void ReleaseHandle(void** handle) {
    *handle = nullptr; /* Note that here we dereference one level 
                          to modify the content of the location 
                          pointed at */
}

In your C# program on the other hand, you should import the function with something like that:

[DllImport("YourLibrary.dll")]
static extern void ReleaseHandle(ref IntPtr handle);

and invoke it by using the ref keyword:

IntPtr value = IntPtr.Add(IntPtr.Zero, 123456789);
ReleaseHandle(ref managedHandle);
Console.WriteLine(managedHandle); // this outputs to 0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM