HOWTO: passing an [in,out] char* from Managed C++ to Unmanaged C.

  • Thread starter Thread starter Sam Carleton
  • Start date Start date
S

Sam Carleton

I am writing Managed C++ code to call in to an Unmanaged C API.
The reason for using Managed C++ over C# is that the Unmanaged C
module is loaded via LoadLibrary(). DllImport cannot be used;
functions pointers and GetProcAddress() is being used.

The API function definition looks like this:

int GetString( [out] char* pszOutStr, [in,out] int *nStrLen)

It looks like the prototyping of the function pointer is straight
forward:

typedef int (*FPGetString)( char* pszOutStr, int *nStrLen);

The question is how do I get a char* with a given length to pass
into this function. Mind you this IS an Ansi call, not Unicode!

Sam
 
I am writing Managed C++ code to call in to an Unmanaged C API.
The reason for using Managed C++ over C# is that the Unmanaged C
module is loaded via LoadLibrary(). DllImport cannot be used;
functions pointers and GetProcAddress() is being used.

The API function definition looks like this:

int GetString( [out] char* pszOutStr, [in,out] int *nStrLen)

It looks like the prototyping of the function pointer is straight
forward:

typedef int (*FPGetString)( char* pszOutStr, int *nStrLen);

The question is how do I get a char* with a given length to pass
into this function. Mind you this IS an Ansi call, not Unicode!

Sam

Ok, looks like an [out] is simple:

int nStrLen = x;
IntPtr ptrOut = Marshal::AllocHGlobal( nStrLen * sizeof(char));
GetString( (char*) ptrOut.ToPointer(), &nStrLen);
Marshal::FreeCoTaskMem(ptrOut);

This is working fine for me. The problem I am having now is the
[in, out]. There is another method that one of the three
parameters which is an in/out is the username. The size of the
username buffer must the full length possible for a username in
this app. The API call might prompt the user and the user might
change the username, so the new username is returned in the same
string that was passed in. Crasy, but that is what I have to work
with. Here is my best guess, which is blowing up when I call Free
the memory:

StringBuilder * outUser = new StringBuilder( user, USER_LEN+1);
IntPtr ptrUsername = Marshal::StringToHGlobalAnsi(outUser->ToString());
// I don't know if the pin is really needed, but it compiles
char __pin* pszUsername = (char*) ptrUsername.ToPointer();

login( pszUsername, ...);

String * strUser = Marshal::PtrToStringAnsi(ptrUsername);

Marshal::FreeCoTaskMem(ptrUsername);

To tell the truth, the username is freed without any problems, it
is the parameter after it, which is also a [in, out] char* that
blows chunks (unhandled exception) when calling
Marshal::FreeCoTaskMem().

Any thoughts?

Sam
 
AllocHGlobal should be paired with FreeHGlobal not FreeCoTaskMem!

Willy.

Sam Carleton said:
I am writing Managed C++ code to call in to an Unmanaged C API.
The reason for using Managed C++ over C# is that the Unmanaged C
module is loaded via LoadLibrary(). DllImport cannot be used;
functions pointers and GetProcAddress() is being used.

The API function definition looks like this:

int GetString( [out] char* pszOutStr, [in,out] int *nStrLen)

It looks like the prototyping of the function pointer is straight
forward:

typedef int (*FPGetString)( char* pszOutStr, int *nStrLen);

The question is how do I get a char* with a given length to pass
into this function. Mind you this IS an Ansi call, not Unicode!

Sam

Ok, looks like an [out] is simple:

int nStrLen = x;
IntPtr ptrOut = Marshal::AllocHGlobal( nStrLen * sizeof(char));
GetString( (char*) ptrOut.ToPointer(), &nStrLen);
Marshal::FreeCoTaskMem(ptrOut);

This is working fine for me. The problem I am having now is the
[in, out]. There is another method that one of the three
parameters which is an in/out is the username. The size of the
username buffer must the full length possible for a username in
this app. The API call might prompt the user and the user might
change the username, so the new username is returned in the same
string that was passed in. Crasy, but that is what I have to work
with. Here is my best guess, which is blowing up when I call Free
the memory:

StringBuilder * outUser = new StringBuilder( user, USER_LEN+1);
IntPtr ptrUsername = Marshal::StringToHGlobalAnsi(outUser->ToString());
// I don't know if the pin is really needed, but it compiles
char __pin* pszUsername = (char*) ptrUsername.ToPointer();

login( pszUsername, ...);

String * strUser = Marshal::PtrToStringAnsi(ptrUsername);

Marshal::FreeCoTaskMem(ptrUsername);

To tell the truth, the username is freed without any problems, it
is the parameter after it, which is also a [in, out] char* that
blows chunks (unhandled exception) when calling
Marshal::FreeCoTaskMem().

Any thoughts?

Sam
 
Back
Top