How to pass C# class object to managed c++ without unsafe modifier? - c#

I am passing a C# object (PSObject) to managed C++ in the following way. But it crashes in the commented statement. Am I missing something?
Am I passing PSObject correctly to managed C++?
or am I accessing it wrongly?
I am using clr:oldsyntax.
Actually C# will pass a PSObject to managed C++,
in managed C++ I want to examine the properties present in PSObject. (An object returned by running PowerShell commands)
In C#, using delegate concept I am calling managed C++ method to pass PSObject.
The delegate is declared as below:
delegate bool CFuncDelegate(PSObject Arg);
funcObj (a IntPtr) is a pointer to addData function in C++ (I didn't write that code here, since it is not relevant) and I am calling addData in csharp as:
CFuncDelegate func = (CFuncDelegate)Marshal.GetDelegateForFunctionPointer(funcObj, typeof(CFuncDelegate));
bool isCompleted = func(psoObject); //psoObject is a PSObject
and in managed C++,
static bool __clrcall addData(System::Management::Automation::PSObject* curPsObj)
{
log(Marshal::StringToHGlobalUni(curPsObj->AdaptedMemberSetName));
//prints psadapted
System::Object* value = curPsObj->Properties->get_Item("DisplayName");
//crashes
}
It would be better if someone just post two lines of code to pass object from C# and accessing it in managed C++. Thanks in advance.

I think it's really time that you abandoned oldsyntax and moved to C++/CLI. Anyway, even doing that is not going to solve your problem. You define a delegate like this:
delegate bool CFuncDelegate(PSObject Arg);
And then you assign a delegate variable like this:
CFuncDelegate func = (CFuncDelegate)Marshal.GetDelegateForFunctionPointer(
funcObj, typeof(CFuncDelegate));
The documentation for Marshal.GetDelegateForFunctionPointer says:
Converts an unmanaged function pointer to a delegate.
So, your code can only work if funcObj is an unmanaged function. And your addData method is certainly not that. You need to stop using GetDelegateForFunctionPointer here. It is simply not compatible with calling the managed function addData.
I've no idea where funcObj comes from. You said:
funcObj (a IntPtr) is a pointer to addData function in cpp (i didnt write that code here, since it is not relevant)
In fact it is not only relevant to the problem, it is the root cause of the problem. What I would expect to see here would be for you to add the C++ assembly to your C# project as a reference, at which point addData could be referenced directly.
Of course, none of this even mentions the fact that your calling conventions are mis-matched. The managed code uses clrcall and your unmanaged function pointer is taken to be stdcall.
Update
There's some more information in the comments. Pass addData as a delegate. You'll need to declare the delegate type in the C# code which I believe you reference from your C++ assembly.

Related

Where function passed as UnmanagedFunctionPointer to C is executed?

In C, there is a function that accepts a pointer to a function to perform comparison:
[DllImport("mylibrary.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int set_compare(IntPtr id, MarshalAs(UnmanagedType.FunctionPtr)]CompareFunction cmp);
In C#, a delegate is passed to the C function:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int CompareFunction(ref IntPtr left, ref IntPtr right);
Currently, I accept Func<T,T,int> comparer in a constructor of a generic class and convert it to the delegate. "mylibrary.dll" owns data, managed C# library knows how to convert pointers to T and then compare Ts.
//.in ctor
CompareFunction cmpFunc = (ref IntPtr left, ref IntPtr right) => {
var l = GenericFromPointer<T>(left);
var r = GenericFromPointer<T>(right);
return comparer(l, r);
};
I also have an option to write a CompareFunction in C for most important data types that are used in 90%+ cases, but I hope to avoid modifications to the native library.
The question is, when setting the compare function with P/Invoke, does every subsequent call to that function from C code incurs marshaling overheads, or the delegate is called from C as if it was initially written in C?
I imagine that, when compiled, the delegate is a sequence of machine instructions in memory, but do not understand if/why C code would need to ask .NET to make the actual comparison, instead of just executing these instructions in place?
I am mostly interested in better understanding how interop works. However, this delegate is used for binary search on big data sets, and if every subsequent call has some overheads as a single P/Invoke, rewriting comparers in native C could be a good option.
I imagine that, when compiled, the delegate is a sequence of machine instructions in memory, but do not understand if/why C code would need to ask .NET to make the actual comparison, instead of just executing these instructions in place?
I guess you're a bit confused about how .NET works. C doesn't ask .NET to execute code.
First, your lambda is turned into a compiler-generated class instance (because you're closing over the comparer variable), and then a delegate to a method of this class is used. And it's an instance method since your lambda is a closure.
A delegate is similar to a function pointer. So, like you say, it points to executable code. Whether this code is generated from a C source or a .NET source is irrelevant at this point.
It's in the interop case when this starts to matter. P/Invoke won't pass your delegate as-is as a function pointer to C code. It will pass a function pointer to a thunk which calls the delegate. Visual Studio will display this as a [Native to Managed Transition] stack frame. This is needed for different reasons such as marshaling or passing additional parameters (like the instance of the class backing your lambda for instance).
As to the performance considerations of this, here's what MSDN says, quite obviously:
Thunking. Regardless of the interoperability technique used, special transition sequences, which are known as thunks, are required each time a managed function calls an native function, and vice-versa. Because thunking contributes to the overall time that it takes to interoperate between managed code and native code, the accumulation of these transitions can negatively affect performance.
So, if your code requires a lot of transitions between managed and native code, you should get better performance by doing your comparisons on the C side if possible, so that you avoid the transitions.

Convert C++ function for use in C#

I have a C++ DLL with partial documentation only and no source code access. I need to use functions of this C++ library in my C# application. This is what I have so far:
[DllImport(cpplib.dll)]
public static extern long someFunctionsWithNoParameters();
When I declare and call a function from the C++ DLL in my C# application like this (function with no arguments) and than call it, it works, the function returns a long value returned by the C++ function.
However I don't know how to handle functions with pointer or reference parameters, or parameters defined as in and out by the C++ function. For example this C++ function:
long functionWithParameters(long &State, char *pName, int nLen)
This is how the function is declared (I have access to the header file of the DLL, but not to the source). The parameters State and pName are declared as out parameters and the parameter nLen is declared as in parameter. How do I declare this C++ function in my C# application under the [DllImport] line and than use it (what form of parameters should I pass in and how to read the out parameters)? Is there some conversion convention between the C/C++ pointer and reference types to some C# types?
Thank you!
You need to declare a matching call convention for the imported function. You could try __cdecl or __stdcall, like this:
[DllImport(cpplib.dll, CallingConvention=CallingConvention.Cdecl)]
public static extern long someFunctionsWithNoParameters();
About pointers and references (which are the same in most practical implementations), you need to use unsafe context and C# pointers, consult MSDN for more detail.

Using Managed Class Method as Callback

I'm currently working on a little Midi Project and just now I'm writing a little "SharpMidi" Library in C++/Cli to make it easier for me to use native Midi functions from Managed code.
I'm now stuck on the midiInOpen Function:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd798458%28v=vs.85%29.aspx
As you can see from the documentation, this function requires an unmanaged function as Callback and optional instance data.
I managed to convert a Managed Function Pointer to an unmanaged Function Pointer using
System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate
but I now have problems converting the this Pointer from my managed class to an unmanaged Pointer, I don't even know if its possibly they way I want it to work.
HMIDIIN _midiInDevice;
void MidiInProcNative(HMIDIIN midiInDevice, UINT msg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
delegate void MidiInProc(HMIDIIN midiInDevice, UINT msg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
MidiInProc^ _midiInProc;
...
_midiInProc = gcnew MidiInDevice::MidiInProc(this, &MidiInDevice::MidiInProcNative);
cli::pin_ptr<HMIDIIN> midiInDevPtr = &_midiInDevice;
pin_ptr<???> thisPtr = this; // This is the line I'm struggling with
MMRESULT result = midiInOpen(midiInDevPtr, devId, (DWORD_PTR)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(_midiInProc).ToPointer(), thisPtr, CALLBACK_FUNCTION);
As you can see I have experimented with pin_ptrs but I don't think this will work as the this pointer can't be used to initialize any pin_ptr.
I hope I could make clear what I want to try to achieve and maybe somebody can help me out.
Regards,
Xaser
I now have problems converting the this Pointer from my managed class to an unmanaged Pointer
Just don't, there's no need for it. The dwCallbackInstance argument of miniInOpen() is a convenience argument for native C++. You get it back in the static callback function, let's you call an instance method of a C++ class.
But delegates are far more powerful than member function pointers, they already encapsulate this. A delegate constructor takes two arguments, the target object and the target method. So that it can automatically call an instance method. You already took advantage of that, you indeed passed this as the first argument. So you can be sure that your MidiInProcNative() instance method uses the proper object reference.
Just pass nullptr for the argument.

C# P/Invoke: Pointer to string as error message

I am attempting to use llvmc as a C# library using P/Invokes(because I can't find any .NET bindings).
However, I've a problem. llvmc uses char** for error passing.
An example would be this:
char* error = NULL;
LLVMVerifyModule(PointerToSomeModule, LLVMAbortProcessAction, &error);
What should I do to allow this function to be used in C# code?
EDIT: The example I found also mentions this call:
LLVMDisposeMessage(error);
I just saw the answers and thought this could be an important detail.
A char** argument is troublesome, there is a memory management problem. If you declare the argument as "out string", the P/Invoke marshaller is going to try to free the pointer. That's very unlikely to work, it requires the string to be allocated with CoTaskMemAlloc().
The only other option you have to declare it as "out IntPtr" and marshal the string yourself with Marshal.PtrToStringAnsi(). That will work, beyond an unpluggable memory leak if LLVMC actually expects you to free the pointer. Call it a million times to verify that. There are a few odds that it won't blow since it is an error message, it might return a pointer to a string literal.
The only option left then is to write a wrapper in the C++/CLI language so you can free the pointer.
Take a look at the StringBuilder class. Or you can also simply declare the parameter as an integer out parameter and use Marshal.PtrToStringAnsi.

C# delegate with string reference to c++ callback

I wrote a C# application that uses an unmanaged c++ dll via managed c++ dll.
In the unmanaged dll, there's a callback that one of its params is std::string&.
I can't seem to find the right way to wrap this with the managed dll.
When I use String^, the callback works, but the C# application does not get anything in the string.
When I used String^%, things started to crash in other places that does not seem to be related (maybe memory corruption).
So my question is, what's the right way to do this?
Thanks
I can't copy-paste code here, but I'll try to explain again.
I can't use marshaling in the managed c++ section because I'm not calling a function, but passing a c# delegate for a callback.
In the unmanaged dll, I have a callback that requires a function like this: void Func(unsigned int, int, std:string &).
My goal is to pass a c# delegate from my program to that callback, so in the unmanaged code,
I made a delegate like this: delegate void DEL(unsigned int a, int b, String ^ c) and a function like: void mFunc(DEL ^ del), and that function marshal's the delegate into a cb that the unmanaged callback subscribe function accepts. The unsigned int and int works fine, but the string is always "" when the C# function is triggered.
Posting some code would help me understand better and give a better answer; but there is no automatic conversion or marshalling of String^ to std::string. You would need to do to marshalling yourself to get the string back to the C# code. A quick search can provide with details on how to do this.
http://msdn.microsoft.com/en-us/library/42zy2z41.aspx
I don't believe that the marshalling can deal with std::string. I think you need to make your own callback that passes char * and then write the glue code between the two.
Also, once the delegate is marshalled into a callback, that callback does not count as a reference to the object that the delegate might have been made from. So if the delegate is not a static method, you need to stuff it somewhere for the lifetime of the unmanaged callback.

Categories

Resources