我有C#项目,我必须使用DllImport使用C++dll。(我有c ++ dll的源代码(
我正在从c ++ dll导入一个函数,如下所示:
[DllImport("Example.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int SendRequest([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] ref string[] fields);
我在 C# 中使用这个函数,如下所示:
List<String> fields = new List<String>();
fields.Add("Test1");
fields.Add("Test2");
string[] fieldsArr = fields.ToArray();
int resultOfSendRequest = SendRequest(ref fieldsArr);
问题出在 c++ dll 中,它将字符串强制转换为某处的 char*,并且读取唯一的第一个字符,而不是整个字符串。
如何在不接触 c++ dll 的情况下解决这个问题。(如果我从 VB6 调用此函数,它可以正常工作。
C++代码是这样的:
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;
//....
}
核心末尾的字段名称 和字符 *名称仅由字符串的第一个字符组成。不是完整的字符串。
在 C 语言中,字符串是一个字节 [],每个字符串都以 '\0' 结尾。 最后一项末尾有两个"\0"的字符串数组。 因此,请尝试以下操作:
[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(" ", fields);
IntPtr fieldsPtr = Marshal.StringToBSTR(fieldsArr);
int results = SendRequest(fieldsPtr);
}
如果它是一个指针数组,则使用此
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);
}