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+发送字符串数组+;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

我在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 = 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的典型症状。