I have C# project and I have to use a C++ dll using DllImport. (I have source codes of c++ dll)
I'm importing a function from c++ dll like this :
[DllImport("Example.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int SendRequest([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] ref string[] fields);
I'm using this function in C# like this :
List<String> fields = new List<String>();
fields.Add("Test1");
fields.Add("Test2");
string[] fieldsArr = fields.ToArray();
int resultOfSendRequest = SendRequest(ref fieldsArr);
Problem is in c++ dll, it casts string to char* in somewhere and it reads the only first character, not entire string.
How can I solve this without touching c++ dll. (If I call this function from VB6 it works without any problem.)
C++ code is like this :
VARIANT vVar;
__declspec( dllexport ) int _stdcall SendRequest (SAFEARRAY**);
int _stdcall SendRequest ( SAFEARRAY** arrayFlds,
short NFlds)
{
// *********** prepare O.i.d, fields name, values
for (long iElem=0; iElem < NFlds; iElem++)
if (LoadElement (&vVar, iElem, &flds[iElem], &pFlds[iElem],*arrayFlds)==-1)
return -1;
//...
}
int LoadElement( VARIANT* vVar,
long iElem,
S_FLDS* flds,
char** pFld,
SAFEARRAY* arrayFlds)
{
hRes = SafeArrayGetElement(arrayFlds, &iElem, pFld);
strcpy(flds->FieldName, *pFld);
flds->bValLen = 0;
char *Name = flds->FieldName;
//....
}
The fieldName and char *Name at the end of the core only consists of first character of string. Not the full string.
In C Langues a string is a byte[] with each string terminated with a '\\0'. An array of strings the last item has two '\\0' at the end. So try following :
[DllImport("Example.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int SendRequest(IntPtr fields);
static void Main(string[] args)
{
List<String> fields = new List<String>();
fields.Add("Test1");
fields.Add("Test2");
string fieldsArr = string.Join("\0", fields);
IntPtr fieldsPtr = Marshal.StringToBSTR(fieldsArr);
int results = SendRequest(fieldsPtr);
}
If it is an array of pointers then use this
public struct Pointers
{
public IntPtr[] pointers;
}
[DllImport("Example.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int SendRequest(IntPtr fields);
static void Main(string[] args)
{
List<String> fields = new List<String>();
fields.Add("Test1");
fields.Add("Test2");
List<IntPtr> pointers = new List<IntPtr>();
foreach (string field in fields)
{
IntPtr intPtr = Marshal.StringToBSTR(field);
pointers.Add(intPtr);
}
Pointers sPointers = new Pointers();
sPointers.pointers = pointers.ToArray();
IntPtr fieldsPtr = IntPtr.Zero;
Marshal.StructureToPtr(sPointers, fieldsPtr, true);
int results = SendRequest(fieldsPtr);
Marshal.FreeHGlobal(fieldsPtr);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.