问题
i asked a question here involving C++ and C# communicating. The problem got solved but led to a new problem.
this returns a String (C#)
return Marshal.PtrToStringAnsi(decryptsn(InpData));
this expects a TCHAR* (C++)
lpAlpha2[0] = Company::Pins::Bank::Decryption::Decrypt::Decryption("123456");
i've googled how to solve this problem, but i am not sure why the String has a carrot(^) on it. Would it be best to change the return from String to something else that C++ would accept? or would i need to do a convert before assigning the value?
回答1:
That is a really rambling way to ask the question, but if you mean how to convert a String ^
to a char *
, then you use the same marshaller you used before, only backwards:
char* unmanagedstring = (char *) Marshal::StringToHGlobalAnsi(managedstring).ToPointer();
Edit: don't forget to release the memory allocated when you're done using Marshal::FreeHGlobal
.
回答2:
String has a ^
because that's the marker for a managed reference. Basically, it's used the same way as *
in unmanaged land, except it can only point to an object type, not to other pointer types, or to void.
TCHAR
is #defined (or perhaps typedefed, I can't remember) to either char
or wchar_t
, based on the _UNICODE preprocessor definition. Therefore, I would use that and write the code twice.
Either inline:
TCHAR* str;
String^ managedString
#ifdef _UNICODE
str = (TCHAR*) Marshal::StringToHGlobalUni(managedString).ToPointer();
#else
str = (TCHAR*) Marshal::StringToHGlobalAnsi(managedString).ToPointer();
#endif
// use str.
Marshal::FreeHGlobal(IntPtr(str));
or as a pair of conversion methods, both of which assume that the output buffer has already been allocated and is large enough. Method overloading should make it pick the correct one, based on what TCHAR is defined as.
void ConvertManagedString(String^ managedString, char* outString)
{
char* str;
str = (char*) Marshal::StringToHGlobalAnsi(managedString).ToPointer();
strcpy(outString, str);
Marshal::FreeHGlobal(IntPtr(str));
}
void ConvertManagedString(String^ managedString, wchar_t* outString)
{
wchar_t* str;
str = (wchar_t*) Marshal::StringToHGlobalUni(managedString).ToPointer();
wcscpy(outString, str);
Marshal::FreeHGlobal(IntPtr(str));
}
回答3:
The syntax String^
is C++/CLI talk for "(garbage collected) reference to a System.String".
You have a couple of options for the conversion of a String
into a C string, which is another way to express the TCHAR*
. My preferred way in C++ would be to store the converted string into a C++ string type, either std::wstring
or std::string
, depending on you building the project as a Unicode or MBCS project.
In either case you can use something like this:
std::wstring tmp = msclr::interop::marshal_as<std::wstring>( /* Your .NET String */ );
or
std::string tmp = msclr::interop::marshal_as<std::string>(...);
Once you've converted the string into the correct wide or narrow string format, you can then access its C string representation using the c_str()
function, like so:
callCFunction(tmp.c_str());
Assuming that callCFunction
expects you to pass it a C-style char*
or wchar_t*
(which TCHAR*
will "degrade" to depending on your compilation settings.
来源:https://stackoverflow.com/questions/5666997/how-do-you-convert-a-systemstring-to-tchar