Dll 封送对字符**数组的引用

Dll 封送对字符**数组的引用,dll,pinvoke,marshalling,Dll,Pinvoke,Marshalling,我无法通过引用封送char*数组。数据在C++非托管侧被正确填充。但是当它通过refererce返回到托管端时,我得到了一个指向第一个数组元素的指针 //The function in C++ extern "C" DATAACCESSLAYERDLL_API void __stdcall DB_SchemaField_GetKeyValues(Schema::TSchemaFieldHandle hField, const char** &keys, const char ** &a

我无法通过引用封送char*数组。数据在C++非托管侧被正确填充。但是当它通过refererce返回到托管端时,我得到了一个指向第一个数组元素的指针

//The function in C++
extern "C" DATAACCESSLAYERDLL_API void  __stdcall DB_SchemaField_GetKeyValues(Schema::TSchemaFieldHandle hField, const char** &keys, const char ** &values)
{
    Schema::CSchemaField *pField = CDataObjectFactory::GetObjectTpl<Schema::CSchemaField>(hField);
    if (!pField) return;
    Schema::TSchemaKeyValuePair::iterator itor = pField->GetKeyValues().begin();

    int index = 0;
    for (itor; itor != pField->GetKeyValues().end(); ++itor)
    {
        keys[index] = (*itor).first.c_str();
        values[index] = (*itor).second.c_str();
        index++;
    }

    return;
}
最后。。。。封送处理的代码

    int keyValueCount = DB_SchemaField_GetKeyValuesCount(GetHandle());
    if (keyValueCount > 0)
    {
        IntPtr[] KeysPtr = new IntPtr[keyValueCount];
        IntPtr[] ValuesPtr = new IntPtr[keyValueCount];

        DB_SchemaField_GetKeyValues(GetHandle(), ref KeysPtr, ref ValuesPtr);
        for (int i = 0; i < keyValueCount; i++)
        {
            string key = Marshal.PtrToStringAnsi(KeysPtr[i]);
            string value = Marshal.PtrToStringAnsi(ValuesPtr[i]);
            if (!String.IsNullOrEmpty(key))
            {
                KeyValues.Add(key, value);
            }
        }
    }
int keyValueCount=DB\u SchemaField\u getkeyvaluescont(GetHandle());
如果(keyValueCount>0)
{
IntPtr[]keyptr=新的IntPtr[keyValueCount];
IntPtr[]值SPTR=新IntPtr[keyValueCount];
DB_SchemaField_GetKeyValues(GetHandle(),ref keyptr,ref ValuesPtr);
对于(int i=0;i
通过引用传递两个
常量字符*
数组是错误的。这对马歇尔来说是一个间接的层次。您需要以下内容:

C++

extern "C" DATAACCESSLAYERDLL_API void  __stdcall DB_SchemaField_GetKeyValues(
    Schema::TSchemaFieldHandle hField, const char** keys, const char ** values)
C#


最好确保使用立即返回的指针,因为
C_str()
返回的C字符串只有在下次修改
std::string
对象之前才有效。

为什么要通过引用传递
char**
?我会删除它
const char**
在非托管端,而
[Out]IntPtr[]
在托管端。@DavidHeffernan我认为他返回的是对字符串数组的引用,而不是指向字符串的指针。所以
const char**&
仍然是正确的签名。@KendallFrey没有。他正在传入一个
const char*
数组,该数组由非托管代码填充。参考号是错误的。请注意,在托管代码中从来没有赋值
keys=…
@DavidHeffernan哦,我不知道P/Invoke会封送回一个未通过ref传递的数组。@KendallFrey它是根据我的回答完成的。你不想使用
字符串而不是
IntPtr
?这似乎很有效!我不知道我们可以这样做。谢谢:)能解释一下原因吗?这不是我所期望的。@KendallFrey即使你能说服封送员对它们进行封送(我不知道你是否能对数组进行封送),它也会对返回的指针调用
CoTaskMemFree
。这是一个错误。
extern "C" DATAACCESSLAYERDLL_API void  __stdcall DB_SchemaField_GetKeyValues(
    Schema::TSchemaFieldHandle hField, const char** keys, const char ** values)
[System.Security.SuppressUnmanagedCodeSecurity()]
[DllImport("DataCore.dll")]
static private extern void DB_SchemaField_GetKeyValues(Int64 pField, 
    [Out] IntPtr[] keys, [Out] IntPtr[] values);