【问题标题】:PInvoke an Array of a Byte ArraysPInvoke 一个字节数组的数组
【发布时间】:2009-04-22 18:07:22
【问题描述】:

我有以下 C 代码:

const BYTE* Items[3];
Items[0] = item1;
Items[1] = item2;
Items[2] = item3;
int result = Generalize(3, Items);

使用 Generalize 的签名为

int __stdcall Generalize(INT count, const BYTE * const * items);

使用 PInvoke 进行调用的最佳方式是什么?

【问题讨论】:

    标签: c# c++ pinvoke


    【解决方案1】:

    我不能保证这是最好的方法,但这是我尝试的第一种方法。

        [DllImport("<unknown>", 
               EntryPoint="Generalize", 
               CallingConvention=CallingConvention.StdCall)]
        public static extern int Generalize(int count, IntPtr[] items);
    
        public static void CallGeneralize()
        {
            var itemCount = 3;
            var items = new IntPtr[itemCount];
    
            items[0] = item1; // where itemX is allocated by Marshal.AllocHGlobal(*)
            items[1] = item2;
            items[2] = item3;
    
            var result = Generalize(itemCount, items);
        }
    

    【讨论】:

    • 这行得通。将问题留一个小时左右,看看是否有人发现更优雅的东西。
    【解决方案2】:

    为什么似乎有这么多人想要避免使用 C++/CLI?如果你不得不问如何使用 P/Invoke,这可能是一个使用 C++/CLI 的提示。

    类似于 JasonRShaver.h

    中的以下内容
    namespace StackOverflow
    {
       public ref class JasonRShaver abstract sealed // "abstract sealed" -> "static"
       {
          public:
        static int Generalize(array<array<BYTE>^>^ items) {
            int count = items->Length;
            std::vector<const BYTE*> arrays(count);
    
            for each (array<BYTE>^ a in items)
            {
                BYTE* bytes = new BYTE[a->Length];
                for (int i=0; i<a->Length; i++)
                    bytes[i] = a[i];
                arrays.push_back(bytes);
            }
    
            int retval = ::Generalize(count, &(arrays[0]));
    
            typedef std::vector<const BYTE*>::const_iterator it_t;
            for (it_t it = arrays.begin(); it != arrays.end(); ++it)
            {
                const BYTE* bytes = *it;
                delete[] bytes;
            }
    
            return retval;
        }
    
       };
    }
    

    这不是生产质量的代码(例如,异常处理),您可以使用pin_ptr&lt;&gt; 等做得更好。但是你大概明白了。

    【讨论】:

    • 是的,那是最好的,但其中有相当数量的“其他”代码,这是唯一存在问题的方法。
    【解决方案3】:

    由于 C++ 没有交错数组,只有多维数组,并且使用 row * column 访问元素,因此您可以在调用之前尝试展平多维数组。

    [DllImport("dllName.dll")]
    private static extern int Generalize(int count, ref byte[] items);
    
    public static int Generalize(int count, byte[,] items)
    {
      return Generalize(count, ref items.Cast<byte>().ToArray());
    }
    

    【讨论】:

    • 当然 C++ 有锯齿状数组。试试int**tmp=new int*[50];tmp[3] = new int[123];
    猜你喜欢
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2014-02-15
    • 2019-05-13
    • 1970-01-01
    • 2015-06-09
    • 1970-01-01
    相关资源
    最近更新 更多