0

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?

1
  • Did you really meant to tag with c++ ? pinvoke only works with c. Commented Sep 25, 2024 at 7:48

3 Answers 3

2

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 (e.g., 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.

Sign up to request clarification or add additional context in comments.

1 Comment

Aye, that would be best, but there is a decent amount of 'other' code in there and this was the only method presenting problems.
1

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

1 Comment

This worked. Leaving the question open for another hour or so to see if anyone finds anything more elegant.
1

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

1 Comment

Of course C++ HAS jagged arrays. Try playing with int**tmp=new int*[50];tmp[3] = new int[123];

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.