Click to See Complete Forum and Search --> : Casting


e2c
January 22nd, 2007, 04:57 AM
Hi Guys,

I've probably posted this in the wrong forum, but anyway i wonder if anyone can help me.

I'm attempting to create a program which interacts with a dll. I'm calling a function in the dll called ptGetContractByName which takes 3 parameters which are ExchangeName, ContractName and ContractDate. These variables are of type ExchNamePtr, ConNamePtr and ConDatePtr.

I've managed to find the typedef for these variable types and they are as follows:
typedef ExchNameStr FAR *ExchNamePtr;
typedef CHAR ExchNameStr[11];

So my problem is, i do not know how to cast a String variable to ExchNamePtr. Does anyone know how i can do this?

Thanks.

Zaccheus
January 22nd, 2007, 04:43 PM
You need to declare the native function in terms of a so-called P/INVOKE.

Here's a simplified version of an example from the C++/CLI standard:


using namespace System::Runtime::InteropServices;

[DllImport("MyCLib.dll")]
extern "C" System::Double Hypotenuse(System::Double s1, System::Double s2);


Do you have the full C signature of the native function you want to call ?
Which parameters are 'input' and which are 'output' ?

e2c
January 23rd, 2007, 03:31 AM
Hi Zaccheus,

I've managed to cast some of my variable by using the following code:

ExchNameStr strExchName;

const char * exName = (const char*)(System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(ExchangeName)).ToPointer();

lstrcpyn(strExchName, exName, sizeof strExchName);

Everything seems to be working, however is this poor coding? will encounter problems by using this method in the future?

Thanks.

Zaccheus
January 23rd, 2007, 04:19 AM
Note that you are mixing native and managed code in the same DLL if you use lstrcpyn like that. This means your assembly is not verifyable, i.e. automatic code checking tools cannot check all the code in your managed DLL.

Also I think there's a memory leak because you are not freeing the HGLOBAL.

From MSDN:
StringToHGlobalAnsi is useful for custom marshaling or when mixing managed and unmanaged code. Since this method allocates the unmanaged memory required for a string, always free the memory by calling FreeHGlobal.
http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.marshal.stringtohglobalansi(VS.80).aspx

e2c
January 23rd, 2007, 05:45 AM
Ok, so as long as i FreeHGlobal it should be fine right? or should i adopt another method?

Zaccheus
January 23rd, 2007, 06:21 AM
I personally prefer to keep managed code and native code in separate DLLs, hence I always compile C++/CLI with the /clr:safe option. That way I can use peverify, FxCop, NUnit, etc on my .net DLLs.

If you are happy to have a mixed native/managed DLL, then I think your code should be ok (assuming you call FreeHGlobal).
:)

e2c
January 23rd, 2007, 08:07 AM
Ok cool, well i dont know much about C++ because i dont do much programming but if i get given another project i will look into your method of doing things.

James2007
January 27th, 2007, 02:57 PM
System::String ^ str = gcnew System::String(L"This is a test string.");

cli::array<wchar_t,1> ^ arChars = str->ToCharArray();

const int nLength = arChars->Length;

wchar_t * pNewBuffer = new wchar_t[nLength + 1];
char * pAnsiBuffer = new char[nLength + 1];

for (int x = 0; x < nLength; ++x)
{
pNewBuffer[x] = arChars[x];
}

pNewBuffer[nLength] = 0;

// Need to include windows.h for WideCharToMultiByte

::WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,pNewBuffer,nLength,pAnsiBuffer,nLength,NULL,NULL);

delete [] pNewBuffer;

pAnsiBuffer[nLength] =0;

// pAnsiBuffer contains the ASCII text you need

// use pAnsiBuffer

...

// then free it

delete [] pAnsiBuffer;



IF the text you are using is guaranteed to be on the ANSI codepage....



System::String ^ str = gcnew System::String(L"This is a test string.");

cli::array<wchar_t,1> ^ arChars = str->ToCharArray();

const int nLength = arChars->Length;

char * pAnsiBuffer = new char[nLength + 1];

for (int x = 0; x < nLength; ++x)
{
pAnsiBuffer[x] = static_cast<char>(arChars[x]);
}

pAnsiBuffer[nLength] = 0;

// do something with pAnsiBuffer

...

// free it

delete [] pAnsiBuffer;

e2c
July 13th, 2007, 05:45 AM
Thanks James,

So would i then use lstrcpyn to assign the value in pAnsiBuffer to strExchName?

e2c
July 13th, 2007, 09:57 AM
Dont worry mate i figured it out