【问题标题】:C# pinvoke marshalling structure containg vector<structure>C# pinvoke 编组结构包含向量<结构>
【发布时间】:2011-01-20 12:34:22
【问题描述】:

我需要调用一个函数,该函数返回一个结构,该结构包含一个 int 和一个 C# 中其他结构的向量,用于 windows ce 6.0 项目:

该功能由第三方提供商(pda的中国制造商)提供,他们只给我提供了.h文件、dll和lib。

我试图在 C# 中调用的函数在 .h 文件中定义为:

DLLGSMADAPTER ApnInfoData* GetAvailApnList();

ApnInfoData结构如下:

typedef struct ApnInfoData
{
    int m_iDefIndex;
    ApnInfoArray m_apnList;
}

typedef struct ApnInfo
{
    DWORD m_dwAuthType;
    TCHAR m_szName[64];
    TCHAR m_szTel[32];
    TCHAR m_szUser[32];
    TCHAR m_szPassword[32];
    TCHAR m_szApnName[32];
}*LPAppInfo;

typedef vector<ApnInfo> ApnInfoArray;

DLLGSMADAPTER 是一个

#define DLLGSMADAPTER _declspec(dllexport)

我的问题是如何在 .net cf 中调用此函数,因为它使用矢量类,我不知道如何编组。

【问题讨论】:

    标签: c#-3.0 compact-framework pinvoke


    【解决方案1】:

    这是不可能的。 P/Invoke 仅设计用于编组 C 类型。您有几个选择:

    • 使用 C++/CLI 围绕 C 库构建托管包装器,然后在 C# 中使用它
    • 围绕 C++ 类型编写 C 包装器,然后 P/Invoke C 包装器
    • 围绕 C++ 类型编写一个 COM 包装器,然后生成一个 com-interop 存根。

    围绕它的最基本的 C 包装器是这样的:

    // creates/loads/whatever your vector<ApnInfo> and casts it to void*, and then returns it through 'handle'
    int GetAppInfoHandle(void **handle);
    
    // casts handle back to vector<ApnInfo> and calls .size()
    int GetAppInfoLength(void *handle);   
    
    // Load into 'result' the data at ((vector<ApnInfo>*)handle)[idx];
    void GetAppInfo(void *handle, int idx, ApnInfo *result);  
    

    【讨论】:

    • 所以我必须创建一个导出此函数的 c 包装器并为每个元素调用 GetAppInfo 以检索我需要的信息,当然我必须调用其他元素以获得句柄和元素数量在我调用 GetAppInfo 之前。感谢您的快速回答
    • 当然,类似的。关键是 C++ 根本不能很好地跨越语言障碍。类型太复杂,C++ 类型本身并没有描述vector 中的实际内存布局。 P/Invoke 可以处理 C 类型,并且由于 C++ 可以伪装成 C……你明白了。
    • 虽然它被标记为正确答案。在我看来,C++/CLI 在 Windows CE 上不可用。
    【解决方案2】:

    仅使用常规的 P/Invoke Interop 就可以在 C# 中包装 std::vector&lt;your_struct&gt;,但它很复杂。

    从 .NET 世界中实例化 C++ 对象的基本思想是从 .NET 中分配 C++ 对象的确切大小,然后调用从 C++ DLL 导出的构造函数来初始化对象,然后您就可以调用任何函数来访问该 C++ 对象,如果任何方法涉及其他 C++ 类,您还需要将它们包装在 C# 类中,对于具有原始类型的方法,您可以简单地 P/Invoke 它们。如果你只有几个方法可以调用,那会很简单,手动编码不会花很长时间。完成 C++ 对象后,调用 C++ 对象的析构函数方法,这也是一个导出函数。如果它没有,那么你只需要从 .NET 中释放你的内存。

    这是一个例子。

    public class SampleClass : IDisposable
    {    
        [DllImport("YourDll.dll", EntryPoint="ConstructorOfYourClass", CharSet=CharSet.Ansi,          CallingConvention=CallingConvention.ThisCall)]
        public extern static void SampleClassConstructor(IntPtr thisObject);
    
        [DllImport("YourDll.dll", EntryPoint="DoSomething", CharSet=CharSet.Ansi,      CallingConvention=CallingConvention.ThisCall)]
        public extern static void DoSomething(IntPtr thisObject);
    
        [DllImport("YourDll.dll", EntryPoint="DoSomethingElse", CharSet=CharSet.Ansi,      CallingConvention=CallingConvention.ThisCall)]
        public extern static void DoSomething(IntPtr thisObject, int x);
    
        IntPtr ptr;
    
        public SampleClass(int sizeOfYourCppClass)
        {
            this.ptr = Marshal.AllocHGlobal(sizeOfYourCppClass);
            SampleClassConstructor(this.ptr);  
        }
    
        public void DoSomething()
        {
            DoSomething(this.ptr);
        }
    
        public void DoSomethingElse(int x)
        {
            DoSomethingElse(this.ptr, x);
        }
    
        public void Dispose()
        {
            Marshal.FreeHGlobal(this.ptr);
        }
    }
    

    详情请看以下链接,

    C#/.NET PInvoke Interop SDK

    (我是SDK工具的作者)

    【讨论】:

    • 为什么?如果您能提供详细信息,我将不胜感激。谢谢!
    • 我进行了快速研究,没有发现任何阻止开发人员从 C# 创建 std::vector 对象并使用 Compact Framework 通过常规 P/Invoke Interop 调用该函数的东西。你能进一步解释一下吗?谢谢!
    • 实例化一个std::vector对象并调用到C++对象中,我们只需要为C++的std::vector分配内存,并调用std::vector的构造函数来初始化该对象然后就可以调用导出DLL的std::vector类的任意函数了。
    • 我继续阅读了几本关于紧凑框架中 Marshal 类的书籍,紧凑版本中缺少一些静态 marshal 方法,这些缺少的方法都不会阻止使用此解决方案包装一个 C++ 类,因此它不适用于紧凑框架的说法是不正确的。我将改进我们的 C# 包装器生成器以支持紧凑的框架。
    • 当我在做compact framework版本时,我发现windows CE有限制,不支持通过compact framework将浮点值类型传递给windows CE DLL,解决方法是添加一个替代原始方法通过传递对浮点类型值的引用来传递浮点类型的值类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-06
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    相关资源
    最近更新 更多