简体   繁体   中英

PInvoke an Array of a Byte Arrays

I have the following C code:

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

with Generalize having a signature of

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

What is the best way to make that call with PInvoke?

I can't guarantee this is the best way, but it's the first way I'd try.

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

Why does it seem that so many people want to avoid C++/CLI? If you have to ask how to use P/Invoke, that might be a hint to use C++/CLI instead.

Something along the lines of the following in 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;
    }

   };
}

This isn't production-quality code (eg, exception handling), and you might be able to do even a better job with pin_ptr<> and the like. But you get the general idea.

Since C++ doesn't have jagged arrays and only multidimensional arrays and accesses elements by using row * column , you could try flattening the multidimensional array before calling.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM