I am using C# code and need to call this method inside a C++ dll.
static std::wstring DecryptData(const std::wstring& strKey);
I've read many things and my best guess would be to pass something that is easier to read for both languages, like char-array or even byte-array and build the wstring in C++ and the string in C# afterwards.
Did anyone do that already?
Edit:
I read the linkes Topic but none of the answers helps me:
Using const
didn't help.
This is what I have now:
C#
[DllImport(DLL_PATH, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.LPWStr)]
public static extern string DecryptData([MarshalAs(UnmanagedType.LPWStr)]string strKey);
C++
extern "C" __declspec(dllexport) const std::wstring DecryptData(const std::wstring& strKey) {
return WlanHelper::CWirelessHelper::DecryptData(strKey);
}
This gives me a PInvokeStackImbalance =/
You may find this question and this question to be relevant. There are two issues:
- P/Invoke does not natively marshal
std::string
/std::wstring
, and
- Possible memory lifetime issues (depends on implementation of
CWirelessHelper::DecryptData
).
An approach is to copy the string to a plain wchar_t*
buffer allocated using CoTaskMemAlloc
(the framework will handle the string conversion and free the allocated memory).
On the unmanaged side, the code becomes:
extern "C" __declspec(dllexport) const wchar_t* DecryptData( wchar_t* strKey) {
std::wstring retstr = WlanHelper::CWirelessHelper::DecryptData(std::wstring(strKey));
const wchar_t* ret = retstr.c_str();
size_t bufsize = wcslen(ret) + 1;
wchar_t* buffer = (wchar_t*)CoTaskMemAlloc(bufsize * sizeof(wchar_t));
wcscpy_s(buffer, bufsize, ret);
return buffer;
}
And on the managed side:
[DllImport(DLL_PATH,
CharSet = CharSet.Unicode,
CallingConvention = CallingConvention.Cdecl)]
static extern string DecryptData(string strKey);