How to convert System::IntPtr to char* - c++-cli

can any body tell How to convert System::IntPtr to char* in managed c++
this is my main function
int main(void)
{
String* strMessage = "Hello world";
CManagedClass* pCManagedClass = new CManagedClass();//working
pCManagedClass->ShowMessage(strMessage);//working
****above said error here***
char* szMessage = (char*)Marshal::StringToHGlobalAnsi(strMessage);
CUnmanagedClass cUnmanagedClass; cUnmanagedClass.ShowMessageBox(szMessage);
Marshal::FreeHGlobal((int)szMessage);
return 0;
}
thanks in advance

I'm not a huge C++/CLI programmer, but the following should work just fine.
IntPtr p = GetTheIntPtr();
char* pChar = reinterpret_cast<char*>(p.ToPointer());
The IntPtr class has a method called ToPointer which returns the address as a void* type. That will be convertible to char* in C++/CLI.
EDIT
Verified this works on VS2008 and VS2015

Instead of
char* szMessage = (char*)Marshal::StringToHGlobalAnsi(strMessage).ToPointer();
Marshal::FreeHGlobal((int)szMessage);
Use
marshal_context conversions.
const char* szMessage = conversions.marshal_as<const char*>(strMessage);
It cleans itself up, the magic of C++ RAII.

Attention!
I want to add something to JaredPar answer.I don't know where your IntPtr is coming from but you should also use pin_ptr in order to prevent the garbage collector from messing up your memory. I did lot of CLR/Native inter op in the past and using pin_ptr is one of those things that I learnt to do in the hard way.
read the following:
click me

Related

Pass LPWSTR to C# [duplicate]

I need to convert my SHA1 (wchar_t*) to a normal String^ in order to use it in a certain function. Any ideas? I tried Google but all the results were the exact opposite of my question. :\
NOTE: I am using C++.NET framework and Windows Forms Applications
Use the constructor; like this:
const wchar_t* const pStr1 = ...;
System::String^ const str1 = gcnew System::String(pStr1);
const char* const pStr2 = ...;
System::String^ const str2 = gcnew System::String(pStr2);
If you're using the standard C++ string classes (std::wstring or std::string), you can get a pointer with the c_str() method. Your code then might be
const std::wstring const std_str1 = ...;
System::String^ const str1 = gcnew System::String(std_str1.c_str());
See System.String and extensive discussion here.
If on doing Dan's solution you get an error cannot convert parameter 1 from 'std::string' to 'const wchar_t *', then you're asking the wrong question. Instead of asking how to convert wchar_t* to String^, you should be asking how to convert std::string to String^.
Use the built-in c_str function to get a plain char* out of the std::string, and pass that to the constructor.
std::string unmanaged = ...;
String^ managed = gcnew String(unmanaged.c_str());
You could also try:
#include <msclr\marshal_cppstd.h>
...
String^ managedString = msclr::interop::marshal_as<String^>(/* std::string or wchar_t * or const wchar_t * */);
You can refer to Overview of Marshaling in C++ for all the supported types you could use

How can i import this Dll

I have a "CLock.dll" have some functions
For example: This is document for a function
__int16 __stdcall dv_get_auth_code(unsigned char* auth);
Function
To gain authorization code of setup card.
Parameters
auth:[out] Return authorization code, 6 characters.
Return
Succeed then return 0.
I need to call this dll in my winform application. I try
[DllImport("CLock.dll",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int dv_get_auth_code([Out]StringBuilder auth);`
and in Main()
My code:
StringBuilder sb = new StringBuilder();
int result = dv_get_auth_code(sb);
But it's working. What should i do? Thank you and have a nice day !
There are two mistakes in the code as presented. The return type is wrong, and no buffer is allocated.
The return type is a 16 bit type, in C# that is short:
[DllImport("Clock.dll")]
public static extern short dv_get_auth_code(StringBuilder auth);
Then to call the function you need to allocate a buffer. I don't know how large that buffer should be, presumably you know that.
StringBuilder sb = new StringBuilder(bufferLengtg);
short result = dv_get_auth_code(sb);
It is always wise for such an API to pass the length of the buffer to the function. Then it can make sure it does not overrun the buffer.

StringToCoTaskMemUni or StringToCoTaskMemAnsi methods can cause hang?

I have the below code in c++/CLI and observing hang while converting the .net string to char * using StringToCoTaskMemAnsi
const char* CDICashInStringStore::CDIGetStringVal( void )
{
unsigned int identifier = (unsigned int)_id;
debug(" cashincdistores--routing call to .Net for CDI String %d", identifier);
NCR::APTRA::INDCDataAccess::IStringValue^ stringValueProvider = (NCR::APTRA::INDCDataAccess::IStringValue^)GetStringProvider()->GetProvider();
String^ strValue = stringValueProvider->GetStringValue(identifier);
debug(" cashincdistores-- going to call StringToCoTaskMemAnsi);
IntPtr iPtr = Marshal::StringToCoTaskMemAnsi(strValue);
debug(" cashincdistores-- StringToCoTaskMemAnsi called);
// use a local (retVal is not needed)
const char * ansiStr = strdup((const char *) iPtr.ToPointer());
Marshal::FreeCoTaskMem(iPtr);
debug(" cashincdistores--got results %d %s",identifier,ansiStr);
// The returned memory will be free() 'ed by the user
return ansiStr;
}
In our logging I can see "cashincdistores-- going to call StringToCoTaskMemAnsi" and suspecting there is a hang after calling the 'StringToCoTaskMemAnsi' method.
Does there is a chance of hang in 'StringToCoTaskMemAnsi' marshalling method. what could cause the hang ?
Why are you using COM in the first place? You don't need any COM in that code.
Disclaimer: You should probably not be returning a const char * someone else will have to free from your function. That's a very easy way to produce memory leaks or multiple free errors.
Ignoring the disclaimer above, you have a couple possibilities:
First way:
#include <msclr/marshal.h>
msclr::interop::marshal_context context;
const char* strValueAsCString = context.marshal_as<const char*>(strValue);
// Probably bad
const char* ansiStr = strdup(strValueAsCString);
The strValueAsCString pointer will remain valid as long as context is in scope.
Another way:
#include <string>
#include <msclr/marshal_cppstd.h>
std::string strValueAsStdString = msclr::interop::marshal_as<std::string>(strValue);
// Probably bad
const char* ansiStr = strdup(strValueAsStdString.c_str());
Here, the std::string manages the lifetime of the string.
See Overview of Marshaling for reference.

C/C++ DLL: Converting a const uint8_t to a String

I haven't seen C++ code in more than 10 years and now I'm in the need of developing a very small DLL to use the Ping class (System::Net::NetworkInformation) to make a ping to some remoteAddress.
The argument where I'm receiving the remoteAddress is a FREObject which then needs to be transformed into a const uint8_t *. The previous is mandatory and I can't change anything from it. The remoteAddress has to be received as a FREObject and later be transformed in a const uint8_t *.
The problem I'm having is that I have to pass a String^ to the Ping class and not a const uint8_t * and I have no clue of how to convert my const uint8_t * to a String^. Do you have any ideas?
Next is part of my code:
// argv[ARG_IP_ADDRESS_ARGUMENT holds the remoteAddress value.
uint32_t nativeCharArrayLength = 0;
const uint8_t * nativeCharArray = NULL;
FREResult status = FREGetObjectAsUTF8(argv[ARG_IP_ADDRESS_ARGUMENT], &nativeCharArrayLength, &nativeCharArray);
Basically the FREGetObjectAsUTF8 function fills the nativeCharArray array with the value of argv[ARG_IP_ADDRESS_ARGUMENT] and returns the array's length in nativeCharArrayLength. Also, the string uses UTF-8 encoding terminates with the null character.
My next problem would be to convert a String^ back to a const uint8_t *. If you can help with this as well I would really appreciate it.
As I said before, non of this is changeable and I have no idea of how to change nativeCharArray to a String^. Any advice will help.
PS: Also, the purpose of this DLL is to use it as an ANE (Air Native Extension) for my Adobe Air app.
You'll need UTF8Encoding to convert the bytes to characters. It has methods that take pointers, you'll want to take advantage of that. You first need to count the number of characters in the converted string, then allocate an array to store the converted characters, then you can turn it into System::String. Like this:
auto converter = gcnew System::Text::UTF8Encoding;
auto chars = converter->GetCharCount((Byte*)nativeCharArray, nativeCharArrayLength-1);
auto buffer = gcnew array<Char>(chars);
pin_ptr<Char> pbuffer = &buffer[0];
converter->GetChars((Byte*)nativeCharArray, nativeCharArrayLength-1, pbuffer, chars);
String^ result = gcnew String(buffer);
Note that the -1 on nativeCharArrayLength compensates for the zero terminator being included in the value.

How do I convert a System::String^ to const char*?

I'm developing an app in C++/CLI and have a csv file writing library in unmanaged code that I want to use from the managed portion. So my function looks something like this:
bool CSVWriter::Write(const char* stringToWrite);
...but I'm really struggling to convert my shiny System::String^ into something compatible. Basically I was hoping to call by doing something like:
if( m_myWriter->Write(String::Format("{0}",someValueIWantToSave)) )
{
// report success
}
using namespace System::Runtime::InteropServices;
const char* str = (const char*) (Marshal::StringToHGlobalAnsi(managedString)).ToPointer();
From Dev Shed.
As mcandre mentions, Marshal::StringToHGlobalAnsi() is correct. But don't forget to free the newly allocated resource with Marshal::FreeHGlobal(), when the string is no longer in use.
Alternatively, you can use the msclr::interop::marshal_as template to create the string resource and automatically release it when the call exits the resource's scope.
There's a list of what types need which conversion in the overview of marshalling in C++.