编组指向指针的指针

时间:2015-12-31 00:57:15

标签: c# pointers pinvoke marshalling dllimport

问题:

我有一个测试应用程序正在寻找连接到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 * *元帅"和变体提出错误的问题。

0 个答案:

没有答案