C#向C+发送字符串数组+;DLL作为安全数组。只获取第一个字符 我有C++项目,我必须使用DLIMPOLL使用C++ DLL。(我有C++ DLL的源代码)< /P> < >我从C++ DLL中导入一个函数,像这样: [DllImport("Example.dll", CallingConvention = CallingConvention.StdCall)] public static extern int SendRequest([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] ref string[] fields); List<String> fields = new List<String>(); fields.Add("Test1"); fields.Add("Test2"); string[] fieldsArr = fields.ToArray(); int resultOfSendRequest = SendRequest(ref fieldsArr);
我在C#中使用这个函数,如下所示:C#向C+发送字符串数组+;DLL作为安全数组。只获取第一个字符 我有C++项目,我必须使用DLIMPOLL使用C++ DLL。(我有C++ DLL的源代码)< /P> < >我从C++ DLL中导入一个函数,像这样: [DllImport("Example.dll", CallingConvention = CallingConvention.StdCall)] public static extern int SendRequest([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] ref string[] fields); List<String> fields = new List<String>(); fields.Add("Test1"); fields.Add("Test2"); string[] fieldsArr = fields.ToArray(); int resultOfSendRequest = SendRequest(ref fieldsArr);,c#,marshalling,C#,Marshalling,我在C#中使用这个函数,如下所示: [DllImport("Example.dll", CallingConvention = CallingConvention.StdCall)] public static extern int SendRequest([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] ref string[] fields); List<String> fields
[DllImport("Example.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int SendRequest([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] ref string[] fields);
List<String> fields = new List<String>();
fields.Add("Test1");
fields.Add("Test2");
string[] fieldsArr = fields.ToArray();
int resultOfSendRequest = SendRequest(ref fieldsArr);
列表字段=新列表();
字段。添加(“Test1”);
字段。添加(“Test2”);
字符串[]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;
//....
}
变型vVar;
__declspec(dllexport)int\u stdcall SendRequest(安全阵列**);
int\u stdcall SendRequest(安全阵列**arrayFlds,
短期非金融违约金)
{
//**********准备O.i.d、字段名称、值
对于(长iElem=0;iElemFieldName,*pFld);
flds->bValLen=0;
char*Name=flds->FieldName;
//....
}
核心末尾的fieldName和char*Name仅由字符串的第一个字符组成。不是完整字符串。在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("\0", fields);
IntPtr fieldsPtr = Marshal.StringToBSTR(fieldsArr);
int results = SendRequest(fieldsPtr);
}
[DllImport(“Example.dll”,CallingConvention=CallingConvention.StdCall)]
公共静态外部int SendRequest(IntPtr字段);
静态void Main(字符串[]参数)
{
列表字段=新列表();
字段。添加(“Test1”);
字段。添加(“Test2”);
string fieldsArr=string.Join(“\0”,字段);
IntPtr fieldsPtr=Marshal.StringToBSTR(fieldsArr);
int结果=发送请求(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);
}
公共结构指针
{
公共IntPtr[]指针;
}
[DllImport(“Example.dll”,CallingConvention=CallingConvention.StdCall)]
公共静态外部int SendRequest(IntPtr字段);
静态void Main(字符串[]参数)
{
列表字段=新列表();
字段。添加(“Test1”);
字段。添加(“Test2”);
列表指针=新列表();
foreach(字段中的字符串字段)
{
IntPtr IntPtr=Marshal.StringToBSTR(字段);
指针.Add(intPtr);
}
指针sPointers=新指针();
sPointers.pointers=指针.ToArray();
IntPtr fieldsPtr=IntPtr.Zero;
Marshal.StructureToPtr(spoints,fieldsPtr,true);
int结果=发送请求(fieldsPtr);
弗里赫格洛瓦尔元帅(fieldsPtr);
}
>但是我需要发送一个SAFAREAR。在C++ DLL中,它使用HRES= SavaRayAccess数据(ArayFLDS,(Vult*)和PDATA);如果我使用您的代码hRes=“E_意外灾难性故障。”则MarshalString.BSTR将创建一个安全数组(在非托管空间中)。看起来函数需要两个参数:arrayFlds和pData。什么是pData?它是在函数之前创建的。字节*pData;我在这里看到的一个问题是,非托管代码似乎会根据是否从VB调用来修改其行为。这太奇怪了,让我怀疑事情是不是真的。你能给我们一个简单的答案吗?@DavidHeffernan好的,我简化了代码。在调试过程中,我可以看到,在LoadElement()函数中,SAFEARRAY*arrayFlds包含了我从c#代码发送的所有字符串。char**pFld具有第一个字符。但最后“fieldName”和“char*Name”只有第一个字符,而不是所有字符串。请注意,如果从VB6使用此dll,则没有问题。看起来VB6字符串数组与c#数组字符串不一样。我不想修改C++ DLL。我应该用C代码来解决这个问题。我不太擅长C++编程。也许这个问题很容易解决,我不知道。当我在做“最小的,完整的,可验证的例子”时,请做一个好的回答。你能给我解释一下为什么如果我从VB6调用这个函数,我会看到Safearrays中的中文字符,它会工作,但是如果我从c#调用这个函数,我会看到Safearrays中发送的确切字符串,它不会工作。这看起来像是编码问题。中文是8位ANSI文本被解释为UTF16的典型症状。