Reputation: 4394
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?
Upvotes: 0
Views: 3211
Reputation: 38346
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());
}
Upvotes: 1
Reputation: 10875
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.
Upvotes: 2
Reputation: 2844
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);
}
Upvotes: 1