C#将字符串数组作为SafeArray发送到C ++ DLL。只获取第一个字符

时间:2018-01-22 10:16:04

标签: c# marshalling

我有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;

    //....
}

coreName和char *核心末尾的名称只包含string的第一个字符。不是完整的字符串。

1 个答案:

答案 0 :(得分:-3)

在C Langues中,字符串是byte [],每个字符串以'\ 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);

        }

如果它是一个指针数组,那么使用这个

       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);

        }