3

I am writing a C# library to be used by native C++ application. I am using C++/CLI as the Interoperability mechanisim.

I require to pass a callback function from C++ to C# (using C++/CLI as the intermediate layer). C# library needs to call the C++ function with a zero terminated string of wide characters; i.e. the prototype of the callback function is

Func(LPCWSTR pszString);

There are other parameters but they are immaterial for this discussion.

I searched net and found Marshal.GetDelegateForFunctionPointer Method wich I can use. The problem with this is that it converts System.String from C# to char* and not wchar_t* which I am looking for.

Also, what is the best method of achieving this- code example including the C++/CLI portion, if possible. C++/CLI dll is dependent on C# dll. Method needs to be called synchronously.

2 Answers 2

9

GetDelegateForFunctionPointer will work, but you need to add a [MarshalAs(UnmanagedType.LPWStr)] attribute to the parameter in your delegate declaration in order for String to get converted into wchar_t*:

delegate void MyDelegate([MarshalAs(UnmanagedType.LPWStr)] string foo)

IntPtr func = ...;
MyDelegate del = (MyDelegate)Marshal.GetDelegateForFunctionPointer(func,
                                 typeof(MyDelegate));

To pass a modifiable string, give a StringBuilder. You need to explicitly reserve space for the unmanaged function to work with:

delegate void MyDelegate([MarshalAs(UnmanagedType.LPWStr)] StringBuilder foo)

StringBuilder sb = new StringBuilder(64); // reserve 64 characters.

del(sb);
Sign up to request clarification or add additional context in comments.

7 Comments

+1 Out of curiosity, is there no way to declare a delegate to have Charset=Charset.Unicode like you do with DLLImport?
Hi Cory. Many thanks. Your answer has actually solved my problem. How can I achieve the following second requirement: delegate void MyDelegate([MarshalAs(UnmanagedType.LPWStr)] string foo, out string val1, out int val2); In other words, C# calls the callback, giving a string parameter, and in C++, based on that string parameters, val1 and val2 need to be passed back to C#
@Anil: For LPSTR and LPWSTR output parameters in p/invoke, use StringBuilder.
Hi Ben, can you please provide an example as Cory did. I am new to C# and C++/CLI world.
@David: Yes there actually is, see my answer. :-)
|
2

See the little-known UnmanagedFunctionPointer attribute, which is like DllImport for delegates, if you'd like to use CharSet or whatnot.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.