问题:
我有一个测试应用程序正在寻找连接到PC的扫描仪。欧洲制造商提供SDK
C++
,并提供一些头文件和其他信息。他们的C++
API填充结构,如下所示。我担心的是将该结构内部返回的char **解引用(Marshaling)为一组字符串。
//
//The struct, as per the manufacturer's C++ header file:
//
typedef struct {
int count;
char** serialNumbers;
} ScannerList;
//
// My interpretation of the struct
//
struct ScannerList
{
public int count;
public IntPtr serialNumbers;
}
//
// C++ API Method Signature:
//
bool SCN_GetScannerList( ScannerList** scannerList );
//
// My DLLImport:
//
[DllImport(@"C:\ScannerSDK\Scanner.dll", CharSet = CharSet.Unicode)]
public static extern bool SCN_GetScannerList(out IntPtr scannerList);
在我的C#包装器类中,我有几个类来包装每个特定的Scanner API调用。对于这种方法,我使用了DllImport所在的ScannerNative类以及struct。这是召唤列表的方法:
private object GetScanlistFromDLL()
{
// our managed code return object - class instead of struct
ScannerNative.ScannerListSafe safeList = new ScannerNative.ScannerListSafe();
// IntPtr to give to the API
IntPtr ptr = new IntPtr();
// unmanaged code struct
ScannerNative.ScannerList scanList = new ScannerNative.ScannerList();
// Call the API with our IntPtr
bool success = ScannerNative.GetScannerList(out ptr);
if(success)
{
// Map the pointer to the type of structure from the API call
scanList = (ScannerNative.ScannerList)Marshal.PtrToStructure(ptr, typeof(ScannerNative.ScannerList));
// copy the unsafe struct members to our safe class
safeList.count = scanList.count;
//Problem - the marshaling returns a string full of garbage
//likely because char** is an array of char* ...
//Not sure how to Marshal a pointer to a pointer to a string :-\
safeList.serialNumbers = Marshal.PtrToStringUni(scanList.serialNumbers);
}
else
{
return null;
}
//
// API call to release unmanaged scanner list ..
//
return safeList;
}
结果:
我确实从API调用
获得了一个看似有效的结构bool success = ScannerNative.GetScannerList(out ptr);
if(成功)块中的后续转换:
if(success)
{
// Map the pointer to the type of structure from the API call
scanList = (ScannerNative.ScannerList)Marshal.PtrToStructure(ptr, typeof(ScannerNative.ScannerList));
这一直有效,直到我们到达 scanList.serialNumbers 成员中存储的 IntPtr ,该成员持有对API结构中char **的引用
scanList.count 显示正确的值' 1' (当连接扫描仪时)但我无法取消 scanList.serialNumbers 成员中保存的字符**。
我已尝试在一对ways中对此进行攻击,但没有任何结果,我要么使用错误的搜索引擎,要么试图找到" c#DllImport Char * *元帅"和变体提出错误的问题。