2009-04-22 22 views
0

Ich habe den folgenden C-Code:PInvoke ein Array von einem Byte Arrays

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

mit Generalize eine Signatur von

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

mit Was ist der beste Weg, diesen Anruf mit PInvoke zu machen?

+0

Welche Wege haben Sie ausprobiert? –

Antwort

1

Ich kann nicht garantieren, dass dies der beste Weg ist, aber es ist der erste Weg, den ich versuchen würde.

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

Das hat funktioniert. Lassen Sie die Frage für eine weitere Stunde offen, um zu sehen, ob jemand etwas eleganteres findet. – JasonRShaver

+0

Danke Micha =) – JasonRShaver

1

Warum scheint es, dass so viele Leute C++/CLI vermeiden wollen? Wenn Sie fragen müssen, wie Sie P/Invoke verwenden, könnte dies ein Hinweis sein, stattdessen C++/CLI zu verwenden.

Etwas nach dem Vorbild der folgenden 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; 
    } 

    }; 
} 

Dies ist nicht serienreifem Code (zB Ausnahmebehandlung), und Sie vielleicht sogar einen besseren Job machen können, mit pin_ptr<> und dergleichen. Aber Sie bekommen die allgemeine Idee.

+0

Aye, das wäre das Beste, aber es gibt eine anständige Menge an "anderem" Code drin und dies war die einzige Methode, die Probleme aufwarf. – JasonRShaver

1

Da C++ keine gezackten Arrays und nur mehrdimensionale Arrays hat und auf Elemente unter Verwendung von row * column zugreift, könnten Sie versuchen, das mehrdimensionale Array vor dem Aufruf abzuflachen.

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

Ich habe es versucht und es hat nicht gut funktioniert. – JasonRShaver

+0

Natürlich hat C++ gezackte Arrays. Versuche es mit 'int ** tmp = new int * [50]; tmp [3] = neuer int [123];' – quetzalcoatl