2012-01-05 23 views
5

Mam natywną bibliotekę z pewnym rodzimym ntype w nim i chciałbym p/wywołać niektóre funkcje w nim.PInvoke - Jak uzyskać odpowiedź "SomeType * []"?

udało mi się zebrać dla:

foo1(ntype** p) ==> foo1(IntPtr[] p) 

Ale nie wiem, jak to zrobić dla:

foo1(ntype*[] p) ==> foo1(<???> p) 

Przynajmniej IntPtr[] nie pracował.

Edit

niezarządzanego funkcja Próbuję zebrać ze jest:

extern mxArray* mclCreateSimpleFunctionHandle(mxFunctionPtr fcn); 

gdzie mxFunctionPtr jest:

typedef void(*mxFunctionPtr)(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]); 

to stanowić wezwanie do następujących funkcji MATLAB podpis:

function [varargout] = callback(varargins) 
%[ 
    %% Do callback code %% 
%] 

Oczywiście, z moimi oczekiwaniami, ta funkcja wskaźnik powinien zapewnić mi z 2 list mxArray*:

  • Lista argumentów wejściowych (tj prhs, zainicjowana na stronie Matlaba)
  • Lista argumentów wyjściowych (tj plhs wszystkie inicjowany do zera, ale w którym powinienem napisać do)

Obecnie z testów zrobiłem, zwraca tylko dla firsts mxArray* w plhs i prhs list

+0

funkcji C, które mają wskaźniki a tablice są beznadziejnie niejednoznaczne. Nie ma różnicy między ntype ** i ntype * [], chyba że w jakiś sposób nadałeś mu inną semantykę w kodzie. –

Odpowiedz

1

dostał

Prawidłowe marshalling dla 'SomeTime* []' w:

extern mxArray* mclCreateSimpleFunctionHandle(mxFunctionPtr fcn); 
typedef void(*mxFunctionPtr)(int nlhs, mxArray* plhs[], int nrhs, mxArray* prhs[]); 

jest:

// For function pointer 
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] 
public delegate void MCRInteropDelegate(int nlhs, 
             [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 0)][Out] IntPtr[] plhs, 
             int nrhs, 
             [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 2)][In] IntPtr[] prhs); 

// For API function 
[DllImport(DLLNAME, EntryPoint = "mclCreateSimpleFunctionHandle", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)] 
private static extern IntPtr _mclCreateSimpleFunctionHandle(MCRInteropDelegate fctn); 

Objaśnienie

MarshalAs cecha wskazuje zebrać SomeTime*[] jako LPArray z IntPtr, gdzie rozmiar tablicy jest zawarty w parametrze funkcyjnego od indeksu od zera do SizeParamIndex

2

pierwszą rzeczą do zrobienia jest, aby tłumaczyć swoim ojczystym ntype w zarządzanym struct.

Na przykład:

public struct Ntype 
{ 
    public int Field1; 
    public long Field2; 
} 

Następnie należy określić metodę z prostym IntPtr parametru w swoim kod C#.

[DllImport] 
static void foo1(IntPtr myParam); 

Wreszcie oto jak go używać:

IntPtr buffer = IntPtr.Zero; 

try 
{ 
    // Allocates a buffer. The size must be known 
    buffer = Marshal.AllocHGlobal(0x1000); 

    // Call to your unmanaged method that fills the buffer 
    foo1(buffer); 

    // Casting the unmanaged memory to managed structure that represents 
    // your data 
    Ntype obj = (Ntype)Marshal.PtrToStructure(buffer, typeof(Ntype)); 
} 
finally 
{ 
    // Free unmanaged memory 
    if (buffer != IntPtr.Zero) 
    { 
     Marshal.FreeHGlobal(buffer); 
    } 
} 
+0

Dlaczego po prostu nie definiuje struktury zarówno w swoim C#, jak i C++, i wysyła adres wskaźnika do kodu C++, sugerowany kod może sprawić, że ludzie będą mieli kłopoty. –

+0

Dzięki @ ken2k i @Ramhound za pomoc. Myślę, że naprawdę nie potrzebuję mieć struktury, tylko wskazówka na to jest w porządku dla mnie. W rzeczywistości próbuję rozwiązać na wywołanie 'mclCreateSimpleFunctionHandle' jak opisano w [link] (http://stackoverflow.com/q/7892254/684399). Najwyraźniej ta funkcja powraca tylko dla wskaźnika do pierwszego 'mxArray *' i próbuję uzyskać pełną listę 'mxArray *' (nie jestem zainteresowany samym 'mxArray ') ... Przynajmniej dla czytelników w tym drugim poście, zgaduję, że jestem na dobrej drodze, żeby to naprawić. – CitizenInsane

Powiązane problemy