0

C# (システム、ゲーム、曲、著作権など) からこの構造体の const char* メンバーにアクセスできるように、これを P/invoke しようとしています。

これは、C++ ヘッダーで定義されている構造体です: gme.hの 79 行目から

struct gme_info_t
{
    /* times in milliseconds; -1 if unknown */
    int length;         /* total length, if file specifies it */
    int intro_length;   /* length of song up to looping section */
    int loop_length;    /* length of looping section */

    /* Length if available, otherwise intro_length+loop_length*2 if available,
    otherwise a default of 150000 (2.5 minutes). */
    int play_length;

    int i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15; /* reserved */

    /* empty string ("") if not available */
    const char* system;
    const char* game;
    const char* song;
    const char* author;
    const char* copyright;
    const char* comment;
    const char* dumper;

    const char *s7,*s8,*s9,*s10,*s11,*s12,*s13,*s14,*s15; /* reserved */
};

私の C# コードでは、この構造体を次のようにモデル化しました。

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct gme_info_t
{
    public int length;
    public int introLength;
    public int loopLength;
    public int playLength;

    public int i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15;

    public string system;
    public string game;
    public string song;
    public string author;
    public string copyright;
    public string comment;
    public string dumper;

    public string s7, s8, s9, s10, s11, s12, s13, s14, s15;
}

今、私が呼び出している関数は、次のような C++ プロトタイプを持つ P/Invoked の関数です。

gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, int track )

はどこgme_err_tですかconst char*

(直接見たい場合は、gme.h の 74 行目を参照してください)

(定義についてはgme.cppの 252 行目を参照)

したがって、すべての typedef を含まない関数は次のようになります。

const char* gme_track_info( Music_Emu const* me, gme_info_t** out, int track )

この関数が機能する方法は、有効な Music_Emu と有効なトラックで呼び出されると、結果はパラメータ 'out' に割り当てられた音楽トラックに関する情報です。

返される const char* は、基本的にエラーが発生した場合のためのものであるため、主な焦点ではありません。「out」パラメータは.

C# でこの関数の P/Invoke を次のように定義しました。

[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern string gme_track_info(IntPtr emuHandle, out gme_info_t trackInfo, int track);

現在、その構造体で著作権文字列を読み取ろうとする私のコードを次に示します。

static void Main()
{

    // Initialize the MusicEmu reference first (this works fine).
    IntPtr emuRef;
    string initEmuRef = NativeMethods.gme_open_file("Adventure Island 4.nsf", out emuRef, 48000);
    Console.WriteLine("Error Message (if any): " + initEmuRef);

    // Now get the track info.
    gme_info_t trackInfo;
    NativeMethods.gme_track_info(emuRef, out trackInfo, 0);
    Console.WriteLine("Copyright: " + trackInfo.copyright); // I get an empty string. When checked with a different NSF reader it prints "1994 Hudson Soft."

    // Keep console window up.
    Console.ReadLine();
}

どんな助けでも大歓迎です。これを機能させるために約4時間試しました。考えられる解決策について、StackOverflow (および一般的なネット) を隅々まで調べましたが、この種の質問に近いものは見つかりませんでした。他のほとんどの問題は、配列の構造体へのポインターへのポインターなどに関するものであり、この場合にはまったく役に立ちません。

その他の情報が必要な場合は、お問い合わせください。喜んで提供いたします。

4

1 に答える 1

0

パラメータtrackInfoout IntPtr. 次に、メソッドを使用して C# 構造体にマーシャリングできますMarshal.PtrToStructure

IntPtr trackInfoPtr;
NativeMethods.gme_track_info(emuRef, out trackInfoPtr);
gme_info_t trackInfo = (gme_info_t)Marshal.PtrToStructure(trackInfoPtr, typeof(gme_info_t));
于 2013-05-31T22:38:26.433 に答える