2012-01-05 13 views
5

Bazı yerel ntype ile yerel bir kütüphaneye sahibim ve içinde bazı işlevleri çağırmak istiyorum. PInvoke - 'SomeType * []' için mareşal nasıl?

Ben sıralamakta başardı:

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

Ama bunu yapmak için nasıl bilmiyorum:

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

En az IntPtr[]

çalıştı olmadı.

Düzenleme

Birlikte sıralamakta çalışıyorum yönetilmeyen fonksiyonudur:

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

Bu aşağıdaki matlab işleve çağrı temsil: mxFunctionPtr olduğunu

extern mxArray* mclCreateSimpleFunctionHandle(mxFunctionPtr fcn); 

imza:

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

Açıkçası, benim beklentilerinden, bu işlev işaretçisi mxArray* 2 listeleri ile beni sağlamalıdır: girdi argümanlardan

  • listesi (yani prhs,) matlab tarafında başlatıldı
  • çıkış argümanları listesi (yani plhs, yaptığım testlerden Şu

, sadece için döner) değişkenlerin ilk ama hangi İçine yazmalıyım yapmak plhs ve prhs listeleri

+0

C işlevleri göstermektedir ve diziler umutsuzca belirsizdir. Bir şekilde kodunuzda farklı anlamlar vermediğiniz sürece ntype ** ve ntype * [] arasında fark yoktur. –

cevap

1

içeri 'SomeTime* []' için doğru manevra

var:

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

geçerli:

01 Nihayet burada

[DllImport] 
static void foo1(IntPtr myParam); 

Kullanmaya nasıl

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

açıklama

MarshalAs özelliği, bir LPArray dizinin büyüklüğü sıfır tabanlı indeksinde işlevin parametresi tarafından ihtiva edilmektedir IntPtr itibarıyla SomeTime*[] sıralamakta işaretçiler almak SizeParamIndex

2

ilk şey ilkleri mxArray* yönetilen struct içine senin yerli ntype çevirmektir. Örneğin

:

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

Sonra C# kodu basit IntPtr parametre ile yöntemini tanımlar.

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

Neden sadece C# ve C++ kodlarındaki yapıyı tanımlamıyor ve işaretçinin adresini C++ koduna göndermiyor, önerilen kodunuz insanların başı belada olabilir. –

+0

Yardımınız için teşekkürler @ ken2k ve @Ramhound. Sanırım yapının olması gerekmiyor, benim için sadece bir işaretçi iyi. Aslında [link] 'de (http://stackoverflow.com/q/7892254/684399) açıklandığı gibi 'mclCreateSimpleFunctionHandle'ı çağırmaya çalışıyorum. Görünüşe göre, bu işlev yalnızca ilk "mxArray *" işaretçisine geri dönüyor ve 'mxArray *' ın tam listesini almaya çalışıyorum ('mxArray'ın kendisi ile ilgilenmiyorum). Bu diğer yazıdaki okuyucular, bunu düzeltmek için yoldayım. – CitizenInsane

İlgili konular