Passing C# string to unmanaged C++ function const char* input parameter - DOTNET

This is a discussion on Passing C# string to unmanaged C++ function const char* input parameter - DOTNET ; Hello, I have been muddling through posts about this sort of thing for days and my understanding is the framework should be able to convert my string to const char* by default (without any kind of explicit conversion/marshalling) but I ...

+ Reply to Thread
Results 1 to 2 of 2

Passing C# string to unmanaged C++ function const char* input parameter

  1. Default Passing C# string to unmanaged C++ function const char* input parameter

    Hello,

    I have been muddling through posts about this sort of thing for
    days and my understanding is the framework should be able to convert my
    string to const char* by default (without any kind of explicit
    conversion/marshalling) but I get the following exception when I do.

    {"Attempted to read or write protected memory. This is often an
    indication that other memory is corrupt."}

    According to VS2005 this exception is thrown by Connect()

    Class Library Code:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;

    namespace Amphire.TeamTrack.API
    {
    public unsafe class TSServer
    {
    [DllImport("TSApiWin32.dll", EntryPoint = "#679")]
    static extern int TSInitializeWinsock();

    [DllImport("TSApiWin32.dll", EntryPoint = "#182",
    CallingConvention = CallingConvention.StdCall)]
    static extern int Connect(string pUserName, string
    pPassword, string pServer);

    public int InitializeWinksock()
    {
    return TSInitializeWinsock();
    }

    public int Connection()
    {

    return Connect("username", "password", "server");
    }

    }
    }

    Executable used for testing:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Amphire.TeamTrack.API;

    namespace Amphire.TeamTrack.Test
    {
    class Tester
    {
    static void Main(string[] args)
    {
    TSServer thisTSServer = new TSServer();
    thisTSServer.InitializeWinksock();
    thisTSServer.Connection();



    }



    }
    }

    C++ Function:

    int TSServer::Connect( const char* userName,
    const char* password,
    const char* serverAddress,
    const char* proxyAddress, /*=NULL*/
    const char* entryPoint /*=NULL*/)
    {
    int len;
    char delim;
    char* host;
    char* hostptr;
    const char* from;
    char szBuffer[1024];

    errorMsg = "";
    TSClearLastError();
    TSSetLastErrorMessage( "" );

    // Some basic error checking
    if ( userName == NULL || *userName == '\0' )
    {
    errorMsg = "TSServer::Connect: No username specified.";
    TSSetLastError( TS_INVALID_USER );
    TSSetLastErrorMessage( errorMsg.GetBuffer() );
    return TSGetLastError();
    }
    if ( password == NULL )
    {
    errorMsg = "TSServer::Connect: No password specified.";
    TSSetLastError( TS_INVALID_USER );
    TSSetLastErrorMessage( errorMsg.GetBuffer() );
    return TSGetLastError();
    }
    if ( serverAddress == NULL || *serverAddress == '\0' )
    {
    errorMsg = "TSServer::Connect: No server address specified.";
    TSSetLastError( TS_ERROR );
    TSSetLastErrorMessage( errorMsg.GetBuffer() );
    return TSGetLastError();
    }

    // If they user passes in a new entry point to teamtrack, store it
    // for socket creation.
    if ( entryPoint != NULL )
    entryPointName = entryPoint;

    // Copy the server address, stripping of leading and trailing spaces
    // and changing backslashes to forward slashes, uppercase to
    lowercase
    host = (char*)malloc( strlen( serverAddress ) + 1 );
    from = serverAddress;
    hostptr = host;
    while ( *from && iswspace( *from ) ) from++;
    while ( *from && !iswspace( *from ) )
    {
    if ( *from == '\\' )
    {
    *hostptr++ = '/';
    from++;
    }
    else
    {
    *hostptr++ = (char)tolower( *from++ );
    }
    }
    *hostptr = '\0';
    hostptr = host;

    // Strip protocol
    if ( strncmp( hostptr, "http://", 7 ) == 0 )
    {
    protocolString = "http";
    portNumber = 80;
    hostptr += 7;
    }
    else if ( strncmp( host, "https://", 8 ) == 0 )
    {
    protocolString = "https";
    portNumber = 443;
    hostptr += 8;
    }
    else
    {
    protocolString = "http";
    portNumber = 80;
    }

    // Strip server name
    len = strcspn( hostptr, ":/" );
    if ( len == 0 )
    {
    errorMsg = "TSServer::Connect: No server address specified.";
    TSSetLastError( TS_ERROR );
    TSAppendLastErrorMessage( errorMsg.GetBuffer() );
    return TSGetLastError();
    }
    delim = hostptr[len];
    hostptr[len] = '\0';
    serverName = hostptr;
    hostptr += len;
    if ( delim != '\0' )
    {
    hostptr++;
    }

    // Strip the port number
    if ( delim == ':' )
    {
    len = strcspn( hostptr, "/" );
    if ( len != 0 )
    {
    delim = hostptr[len];
    hostptr[len] = '\0';
    int nTmpPort = atol( hostptr );
    if ( nTmpPort > 0 )
    {
    portNumber = nTmpPort;
    }
    hostptr += len;
    if ( delim != '\0' )
    {
    hostptr++;
    }
    }
    }

    directoryName = "tmtrack";
    dllName = "tmtrack.dll?";
    len = strlen( hostptr );
    if ( len > 0 )
    {
    // Get the directory and dll names
    char* cp;

    // If the last character is a question mark or slash, strip it off
    cp = &hostptr[ len - 1 ];
    if ( *cp == '?' || *cp == '/' )
    {
    len--;
    hostptr[ len ] = '\0';
    }

    // if a dll is specified
    if ( ( len > 4 ) && ( strcmp( &hostptr[ len - 4 ], ".dll" ) == 0 )
    )
    {
    // Strip off the dll name
    cp = strrchr( hostptr, '/' );
    if ( cp == NULL )
    {
    // No more slashes, rest of string must be the dll
    dllName = hostptr;
    directoryName = "";
    }
    else
    {
    dllName = &cp[1];
    *cp = '\0';
    // rest of string must be directory name
    directoryName = hostptr;
    }
    dllName += "?";
    }
    else
    {
    directoryName = hostptr;
    }
    }

    free( host );

    if ( proxyAddress != NULL )
    {
    proxyString = proxyAddress;
    }

    TSString authentication;
    authentication = userName;
    authentication += ":";
    authentication += password;
    authString = "Authorization: Basic ";
    authString += EncodePassword( authentication.GetBuffer());

    sprintf( szBuffer, "%s://%s:%d/%s/%s",
    protocolString.GetBuffer(),
    serverName.GetBuffer(),
    portNumber,
    directoryName.GetBuffer(),
    dllName.GetBuffer() );
    dllWebAddress = szBuffer;

    // Before we call any function that talks to the server, delete the
    // socket (if it exists) in order to re-create our connection. The
    // socket cache's connection info like the authentication string so
    // we need to delete the socket so that all the connection info will
    // be reset.
    if ( m_pSocket )
    {
    delete m_pSocket;
    m_pSocket = NULL;
    }

    // Now validate the API version which will also validate and
    // authenticate the user.
    int nReturn = ValidateVersion();
    if ( nReturn != TS_OK )
    {
    // 0 is a version failure.
    if ( nReturn == 0 )
    {
    TSSetLastError( TS_INVALID_VERSION );
    TSAppendLastErrorMessage( "TSServer::Connect: Error validating
    version" );
    }
    else // < 0 is another kind of error;
    {
    TSSetLastError( nReturn );
    TSAppendLastErrorMessage( "TSServer::Connect: Some other kind of
    error validating version" );
    }
    return TSGetLastError();
    }

    return TS_OK;
    }


    Anyone have any ideas as to what else I should be doing?


  2. Default Re: Passing C# string to unmanaged C++ function const char* input parameter


    "Mike Price" <idflyfish@hotmail.com> wrote in message
    news:1151594125.087308.194680@d56g2000cwd.googlegroups.com...
    > Hello,
    >
    > I have been muddling through posts about this sort of thing for
    > days and my understanding is the framework should be able to convert my
    > string to const char* by default (without any kind of explicit
    > conversion/marshalling) but I get the following exception when I do.
    >
    > {"Attempted to read or write protected memory. This is often an
    > indication that other memory is corrupt."}


    > According to VS2005 this exception is thrown by Connect()


    Why do you (still) use char* strings? They are ANSI and not international
    compatible.

    [DllImport("TSApiWin32.dll", EntryPoint = "#182",
    CallingConvention=CallingConvention.Cdecl)]
    static extern int Connect(
    [MarshalAs(UnmanagedType.LPStr)] string pUserName,
    [MarshalAs(UnmanagedType.LPStr)] string pPassword,
    [MarshalAs(UnmanagedType.LPStr)] string pServer); // declare
    option types as well if you need to


    > Class Library Code:
    >
    > using System;
    > using System.Collections.Generic;
    > using System.Text;
    > using System.Runtime.InteropServices;
    >
    > namespace Amphire.TeamTrack.API
    > {
    > public unsafe class TSServer
    > {
    > [DllImport("TSApiWin32.dll", EntryPoint = "#679")]
    > static extern int TSInitializeWinsock();
    >
    > [DllImport("TSApiWin32.dll", EntryPoint = "#182",
    > CallingConvention = CallingConvention.StdCall)]
    > static extern int Connect(string pUserName, string
    > pPassword, string pServer);
    >
    > public int InitializeWinksock()
    > {
    > return TSInitializeWinsock();
    > }
    >
    > public int Connection()
    > {
    >
    > return Connect("username", "password", "server");
    > }
    >
    > }
    > }
    >
    > Executable used for testing:
    >
    > using System;
    > using System.Collections.Generic;
    > using System.Text;
    > using Amphire.TeamTrack.API;
    >
    > namespace Amphire.TeamTrack.Test
    > {
    > class Tester
    > {
    > static void Main(string[] args)
    > {
    > TSServer thisTSServer = new TSServer();
    > thisTSServer.InitializeWinksock();
    > thisTSServer.Connection();
    >
    >
    >
    > }
    >
    >
    >
    > }
    > }
    >
    > C++ Function:
    >
    > int TSServer::Connect( const char* userName,
    > const char* password,
    > const char* serverAddress,
    > const char* proxyAddress, /*=NULL*/
    > const char* entryPoint /*=NULL*/)
    > {
    > int len;
    > char delim;
    > char* host;
    > char* hostptr;
    > const char* from;
    > char szBuffer[1024];
    >
    > errorMsg = "";
    > TSClearLastError();
    > TSSetLastErrorMessage( "" );
    >
    > // Some basic error checking
    > if ( userName == NULL || *userName == '\0' )
    > {
    > errorMsg = "TSServer::Connect: No username specified.";
    > TSSetLastError( TS_INVALID_USER );
    > TSSetLastErrorMessage( errorMsg.GetBuffer() );
    > return TSGetLastError();
    > }
    > if ( password == NULL )
    > {
    > errorMsg = "TSServer::Connect: No password specified.";
    > TSSetLastError( TS_INVALID_USER );
    > TSSetLastErrorMessage( errorMsg.GetBuffer() );
    > return TSGetLastError();
    > }
    > if ( serverAddress == NULL || *serverAddress == '\0' )
    > {
    > errorMsg = "TSServer::Connect: No server address specified.";
    > TSSetLastError( TS_ERROR );
    > TSSetLastErrorMessage( errorMsg.GetBuffer() );
    > return TSGetLastError();
    > }
    >
    > // If they user passes in a new entry point to teamtrack, store it
    > // for socket creation.
    > if ( entryPoint != NULL )
    > entryPointName = entryPoint;
    >
    > // Copy the server address, stripping of leading and trailing spaces
    > // and changing backslashes to forward slashes, uppercase to
    > lowercase
    > host = (char*)malloc( strlen( serverAddress ) + 1 );
    > from = serverAddress;
    > hostptr = host;
    > while ( *from && iswspace( *from ) ) from++;
    > while ( *from && !iswspace( *from ) )
    > {
    > if ( *from == '\\' )
    > {
    > *hostptr++ = '/';
    > from++;
    > }
    > else
    > {
    > *hostptr++ = (char)tolower( *from++ );
    > }
    > }
    > *hostptr = '\0';
    > hostptr = host;
    >
    > // Strip protocol
    > if ( strncmp( hostptr, "http://", 7 ) == 0 )
    > {
    > protocolString = "http";
    > portNumber = 80;
    > hostptr += 7;
    > }
    > else if ( strncmp( host, "https://", 8 ) == 0 )
    > {
    > protocolString = "https";
    > portNumber = 443;
    > hostptr += 8;
    > }
    > else
    > {
    > protocolString = "http";
    > portNumber = 80;
    > }
    >
    > // Strip server name
    > len = strcspn( hostptr, ":/" );
    > if ( len == 0 )
    > {
    > errorMsg = "TSServer::Connect: No server address specified.";
    > TSSetLastError( TS_ERROR );
    > TSAppendLastErrorMessage( errorMsg.GetBuffer() );
    > return TSGetLastError();
    > }
    > delim = hostptr[len];
    > hostptr[len] = '\0';
    > serverName = hostptr;
    > hostptr += len;
    > if ( delim != '\0' )
    > {
    > hostptr++;
    > }
    >
    > // Strip the port number
    > if ( delim == ':' )
    > {
    > len = strcspn( hostptr, "/" );
    > if ( len != 0 )
    > {
    > delim = hostptr[len];
    > hostptr[len] = '\0';
    > int nTmpPort = atol( hostptr );
    > if ( nTmpPort > 0 )
    > {
    > portNumber = nTmpPort;
    > }
    > hostptr += len;
    > if ( delim != '\0' )
    > {
    > hostptr++;
    > }
    > }
    > }
    >
    > directoryName = "tmtrack";
    > dllName = "tmtrack.dll?";
    > len = strlen( hostptr );
    > if ( len > 0 )
    > {
    > // Get the directory and dll names
    > char* cp;
    >
    > // If the last character is a question mark or slash, strip it off
    > cp = &hostptr[ len - 1 ];
    > if ( *cp == '?' || *cp == '/' )
    > {
    > len--;
    > hostptr[ len ] = '\0';
    > }
    >
    > // if a dll is specified
    > if ( ( len > 4 ) && ( strcmp( &hostptr[ len - 4 ], ".dll" ) == 0 )
    > )
    > {
    > // Strip off the dll name
    > cp = strrchr( hostptr, '/' );
    > if ( cp == NULL )
    > {
    > // No more slashes, rest of string must be the dll
    > dllName = hostptr;
    > directoryName = "";
    > }
    > else
    > {
    > dllName = &cp[1];
    > *cp = '\0';
    > // rest of string must be directory name
    > directoryName = hostptr;
    > }
    > dllName += "?";
    > }
    > else
    > {
    > directoryName = hostptr;
    > }
    > }
    >
    > free( host );
    >
    > if ( proxyAddress != NULL )
    > {
    > proxyString = proxyAddress;
    > }
    >
    > TSString authentication;
    > authentication = userName;
    > authentication += ":";
    > authentication += password;
    > authString = "Authorization: Basic ";
    > authString += EncodePassword( authentication.GetBuffer());
    >
    > sprintf( szBuffer, "%s://%s:%d/%s/%s",
    > protocolString.GetBuffer(),
    > serverName.GetBuffer(),
    > portNumber,
    > directoryName.GetBuffer(),
    > dllName.GetBuffer() );
    > dllWebAddress = szBuffer;
    >
    > // Before we call any function that talks to the server, delete the
    > // socket (if it exists) in order to re-create our connection. The
    > // socket cache's connection info like the authentication string so
    > // we need to delete the socket so that all the connection info will
    > // be reset.
    > if ( m_pSocket )
    > {
    > delete m_pSocket;
    > m_pSocket = NULL;
    > }
    >
    > // Now validate the API version which will also validate and
    > // authenticate the user.
    > int nReturn = ValidateVersion();
    > if ( nReturn != TS_OK )
    > {
    > // 0 is a version failure.
    > if ( nReturn == 0 )
    > {
    > TSSetLastError( TS_INVALID_VERSION );
    > TSAppendLastErrorMessage( "TSServer::Connect: Error validating
    > version" );
    > }
    > else // < 0 is another kind of error;
    > {
    > TSSetLastError( nReturn );
    > TSAppendLastErrorMessage( "TSServer::Connect: Some other kind of
    > error validating version" );
    > }
    > return TSGetLastError();
    > }
    >
    > return TS_OK;
    > }
    >
    >
    > Anyone have any ideas as to what else I should be doing?
    >



+ Reply to Thread

Similar Threads

  1. string or const char * in a function parameter list ?
    By Application Development in forum c++
    Replies: 3
    Last Post: 08-23-2007, 08:23 AM
  2. const char* vs string
    By Application Development in forum c++
    Replies: 14
    Last Post: 06-04-2007, 09:03 AM
  3. Passing String to Unmanaged Code
    By Application Development in forum DOTNET
    Replies: 8
    Last Post: 06-01-2007, 06:30 AM
  4. Replies: 3
    Last Post: 05-26-2006, 01:20 PM
  5. Re: passing null input parameter
    By Application Development in forum ADO DAO RDO RDS
    Replies: 0
    Last Post: 11-28-2005, 10:07 PM