2016-08-10 10 views
1

このCコードをC#のラッパークラスで使用します。構造体ポインタや関数ポインタなど、さまざまなパラメータを持つ関数があります。構造体を含むマーシャリング/ピンポインティング関数ポインタ

Cコード:

struct wiringPiNodeStruct 
{ 
    int  pinBase ; 
    int  pinMax ; 

    int   fd ; // Node specific 
    unsigned int data0 ; // ditto 

    void (*pinMode)   (struct wiringPiNodeStruct *node, int pin, int mode) ; 

    struct wiringPiNodeStruct *next ; 
} ; 

Iは、上記のコードをマーシャリングしようとしました。しかし、構造体と構造体を含む関数ポインタの適切な解決策を見つけることができません。

C#コード:

[StructLayout(LayoutKind.Sequential)] 
public struct wiringPiNodeStruct 
{ 
    public int pinBase; 
    public int pinMax; 

    public int fd; // Node specific 
    public uint data0; // ditto 


    public delegate void pinMode (struct wiringPiNodeStruct IntPtr node, int pin, int mode) ; 

    public struct wiringPiNodeStruct *next ; 
}; 
+0

リンクされたリストは難解です。 p/invokeで痛みの世界になる。もちろん、私たちはあなたの問題が何であるか全く分かりません。あなたは管理者から非管理者にマーシャリングしています。このリンクされたリストをマネージコードから読み込む方法がわかりません。または、アンマネージコードに埋め込まれたそのようなリストをどのように歩くかわからない場合。現実的には、C++/CLIからこれを行う方がはるかに簡単です。今、あなたのための質問。この質問は無視しないでください。 CまたはC++でリンクリストをコード化したことがありますか?もしあなたがいなければ、あなたはほとんど希望がないからです。歩く前に走ってはいけません。 –

+0

私はC#でかなり新しいです。また、管理され、マーシャリングという用語も新しいものです。私はこの構造を使用するfucntions用のC#でラッパークラスを作成しています。私はC#で上記の構造を使用したい。つまり、私は構造体を再作成したいと思います。マーシャリングして、.netとcの間でメモリを変換するようにしてください。いいえ、私はリンクされたリストをコード化していません。 –

+0

それはやや難しいでしょう。私はあなたの経験のレベルを与えられたこの先進的な何かを試みることは生産的ではないと考えています。私があなたの上司だったら、このライブラリの感触とリンクされたリストの使い方を得るために、C++でいくつかのサンプルコードを書くことをお勧めします。あなたが以前に見たことがないならば、リンクされたリストはかなりトリッキーです。そして、p/invokeの合併症でそれらを学ぼうとする試みは、私の見解では全く生産的ではありません。あなたはそのような時間を浪費します。 –

答えて

0

あなたが前にリンクされたリストを使用したかどうか、重要ではありませ、または...あなたがここに持っていることは「後継者」をit'sを指してフィールドを持つだけの構造であり、しません。もちろん、私が提案したいソリューションが修正なしで動作することを保証するものではありません。しかし、私はP/Invokeでかなり多く作業しています。そのようなことを試してみてください...少なくとも、それはうまくいけば、あなたにアイデアを与えるでしょう。

簡略化のために(そしてマーシャリングの魔法をいくつか取り上げる)私はpinModenextIntPtrフィールドと宣言します。 IntPtrのサイズは32ビットと64ビットで異なることに注意してください。管理対象と非管理対象のコンポーネントが同じビット数を使用していることを確認してください。

delegate void pinMode (IntPtr node, int pin, int mode); 

[StructLayout(LayoutKind.Sequential)] 
internal struct wiringPiNodeStruct 
{ 
    public int pinBase; 
    public int pinMax; 
    public int fd; 
    public uint data0; 
    public IntPtr pinMode; 
    public IntPtr next 
}; 

2つのシナリオに直面することがあります。構造体を読み込んで処理するか、アンマネージコードに作成して渡したいだけです。読書部を見てみましょう。リストを反復すると、そのようになります...

wiringPiNodeStruct node = ... 
while (node.next != IntPtr.Zero) 
{ 
    wiringPiNodeStruct next; 
    next = (wiringPiNodeStruct) Marshal.PtrToStructure(
     node.next, 
     typeof(wiringPiNodeStruct)); 

    ... 

    node = next; 
} 

あなたがpinMode関数を呼び出す/必要性をしたい場合は、あなたがそのような何かを試みることができる...

wiringPiNodeStruct node = ... 
wiringPiNodeStruct next = (wiringPiNodeStruct) Marshal.PtrToStructure(
    node.next, 
    typeof(wiringPiNodeStruct)); 

pinMode func = (pinMode) Marshal.GetDelegateForFunctionPointer(
    next.pinMode, 
    typeof(pinMode)); 

func(node.next, 0, 0); 

今let'sを作成します構造;これはもちろん簡単な例です...列挙可能なデータソースからリンクリスト構造を作成できるいくつかのヘルパユーティリティを作成し、割り当てられたメモリを追跡し、不要になった管理対象メモリを適切に解放します。 pinModeが管理されていない部分でコールバックとして使用されている場合

var second = new wiringPiNodeStruct { }; 

int size = Marshal.SizeOf(typeof(wiringPiNodeStruct)); 
IntPtr pSecond = Marshal.AllocHGlobal(size); 
Marshal.StructureToPtr(second, pSecond, true); 

pinMode func = new pinMode((ptr, pin, mode) => { }); 

var first = new wiringPiNodeStruct { }; 
first.pinMode = Marshal.GetFunctionPointerForDelegate(func); 
first.next = pSecond; 

funcpinModeフィールドに格納されたポインタと同じ寿命を持っていることを確認してください。

wiringPiNodeStructタイプの異なる宣言で再生することもできます。読んだり書いたりするのに適した宣言を持つ方が簡単な場合もあります...

関連する問題