Click to See Complete Forum and Search --> : Problem in calling C++ dll from C# Code


kuldeept
November 23rd, 2005, 04:08 AM
Hi!

I am calling a C++ dll function from my C# code . but facing the problem in a function called inside that C++ function.

That's how I'm referring to the C++ dll function inside my C# class :

class TestInterop
{
[DllImport("DBApi.dll", EntryPoint="DeleteRecFromDB",
ExactSpelling=false,SetLastError=true, CharSet=CharSet.Unicode)]

internal extern static int
DeleteRecFromDB([MarshalAs(UnmanagedType.LPWStr)]string
empName,[MarshalAs(UnmanagedType.LPWStr)]string deptName);
public TestInterop(){}

static void Main(string[] args)
{
TestInterop.DeleteRecFromDB("KT","Dep-01");
}

}

Now my C++ function is written in DBApi.cpp as:

DBApiReturns DeleteRecFromDB(CString empID,
CString depName){
try
{
int returns;
//check for required field
if ( CheckRequiredField(empID) == FALSE )
return MissingRequiredField;
if ( CheckRequiredField(depName) == FALSE )
return MissingRequiredField;

pServerInterface->DeleteRec(CComBSTR(empID),CComBSTR(depName),&returns);

if( returns != 1)
return (Success);
else
return(Failure);
}
catch(_com_error &ce)
{
return COMError ;
}
catch(...)
{
return UnknownError ;
}

}

When I call this function , I get 'UnknownError' on the function CheckRequiredField().If I bypass this function the code works fine.CheckRequiredField() is define as following:

CheckRequiredField(CString field)
{
if ( field.GetLength() <= 0) return FALSE;
return TRUE;
}

I suspect that there must be some problem in the way I'm doing the parameter marshalling.

Please Help.

thanks and regards
KT.

Alex F
November 23rd, 2005, 10:16 AM
Function with CString parameter cannot be called from C#. C# has no idea about MFC/ATL CString type. Replace parameters type to plain string pointer: LPTSTR or LPWSTR. Inside of this function you can create CString variables from these pointers.

kuldeept
November 23rd, 2005, 10:37 PM
Thanks! Alex

When I print empId and depName inside DeleteRecFromDB(CString empID, CString depName), I am getting their correct value(same as what I passed from C# code).

Problem is caused when I call the function CheckRequiredField(CString field). inside DeleteRecFromDB(CString empID, CString depName).

If I comment these calls ,I get the correct results.

Thnaks for your inputs.

Regards.
KT.

darwen
November 26th, 2005, 04:38 PM
Use of CString in this way will bring unexpected results. You should do what you're told : follow the standard for passing of strings which is like this :


// C++
void MyMethod(LPSTR szString, int *pnLength)
{
const CString sString = "ToReturn";

if (szString == NULL)
{
*pnLength = sString.GetLength();
}
else
{
const int nToCopy = min(*pnLength, sString.GetLength());
::strncpy(szString, sString, nToCopy);
*pnLength = nToCopy;
}
}

// in C#
public class MyExample
{
[DllImport("MyDll.dll")]
static public extern void MyMethod([MarshalAs(UnmanagedType.LPStr) StringBuilder stringBuilder, ref int length);

public string CallMyMethod()
{
StringBuilder stringBuilder = new StringBuilder();
int length = 0;

MyMethod(null, ref length);

stringBuilder.Length = lengthl

MyMethod(stringBuilder, ref length);

return stringBuilder.ToString();
}
}


This will work in all cases.

I highly recommend you follow the standards.

Darwen.

kuldeept
November 28th, 2005, 06:23 AM
Thanks Darwen!

I followed the approach, you mentioned and everyrhing is working fine now.

Regards.
KT.