封送对 char** 数组的引用
Marshaling a reference to a char** array
我在通过引用编组 char* 数组时遇到问题。数据在 C++ 非托管端正确填写。但是当它通过引用返回到托管端时,我最终得到一个指向第一个数组元素的指针。
//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;
}
pInvoke 声明
[System.Security.SuppressUnmanagedCodeSecurity()]
[DllImport("DataCore.dll")]
static private extern void DB_SchemaField_GetKeyValues(Int64 pField,
[In, Out] ref IntPtr[] keys, [In, Out] ref IntPtr[] values);
最后...编组的代码
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);
}
}
}
通过引用传递两个 const char*
数组是错误的。对于编组器来说,这是一个太过分的间接级别。您需要以下内容:
C++
extern "C" DATAACCESSLAYERDLL_API void __stdcall DB_SchemaField_GetKeyValues(
Schema::TSchemaFieldHandle hField, const char** keys, const char ** values)
C#
[System.Security.SuppressUnmanagedCodeSecurity()]
[DllImport("DataCore.dll")]
static private extern void DB_SchemaField_GetKeyValues(Int64 pField,
[Out] IntPtr[] keys, [Out] IntPtr[] values);
您最好确保使用立即返回的指针,因为c_str()
返回的C字符串仅在std::string
对象的下一次修改之前有效。
我在通过引用编组 char* 数组时遇到问题。数据在 C++ 非托管端正确填写。但是当它通过引用返回到托管端时,我最终得到一个指向第一个数组元素的指针。
//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;
}
pInvoke 声明
[System.Security.SuppressUnmanagedCodeSecurity()]
[DllImport("DataCore.dll")]
static private extern void DB_SchemaField_GetKeyValues(Int64 pField,
[In, Out] ref IntPtr[] keys, [In, Out] ref IntPtr[] values);
最后...编组的代码
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);
}
}
}
通过引用传递两个 const char*
数组是错误的。对于编组器来说,这是一个太过分的间接级别。您需要以下内容:
C++
extern "C" DATAACCESSLAYERDLL_API void __stdcall DB_SchemaField_GetKeyValues(
Schema::TSchemaFieldHandle hField, const char** keys, const char ** values)
C#
[System.Security.SuppressUnmanagedCodeSecurity()]
[DllImport("DataCore.dll")]
static private extern void DB_SchemaField_GetKeyValues(Int64 pField,
[Out] IntPtr[] keys, [Out] IntPtr[] values);
您最好确保使用立即返回的指针,因为c_str()
返回的C字符串仅在std::string
对象的下一次修改之前有效。