C# pinvoke marshalling structure containg vector

后端 未结 2 1800
一生所求
一生所求 2020-12-03 20:33

I\'m in need to call an function that return an structure that contains an int and an vector of other structures in C# for a windows ce 6.0 project:

The function is

相关标签:
2条回答
  • This is not possible. P/Invoke is designed to marshal C types only. You have a few options:

    • Use C++/CLI to build a managed wrapper around your C library and then use it from C#
    • Write a C wrapper around your C++ types and then P/Invoke the C wrapper
    • Write a COM wrapper around the C++ types and then generate a com-interop stub.

    The most basic C wrapper around this would go something like this:

    // 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);  
    
    0 讨论(0)
  • 2020-12-03 20:57

    Wrapping a std::vector<your_struct> in C# is possible with just regular P/Invoke Interop, it is complicated though.

    The basic idea of instantiating a C++ object from .NET world is to allocate exact size of the C++ object from .NET, then call the constructor which is exported from the C++ DLL to initialize the object, then you will be able to call any of the functions to access that C++ object, if any of the method involves other C++ classes, you will need to wrap them in a C# class as well, for methods with primitive types, you can simply P/Invoke them. If you have only a few methods to call, it would be simple, manual coding won't take long. When you are done with the C++ object, you call the destructor method of the C++ object, which is a export function as well. if it does not have one, then you just need to free your memory from .NET.

    Here is an example.

    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);
        }
    }
    

    For the detail, please see the below link,

    C#/.NET PInvoke Interop SDK

    (I am the author of the SDK tool)

    0 讨论(0)
提交回复
热议问题