Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
143 views
in Technique[技术] by (71.8m points)

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.

question from:https://stackoverflow.com/questions/65933599/marshal-a-variable-from-c-sharp-to-void-in-native-c-and-change-the-variable-v

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...