简体   繁体   中英

How do I get P/Invoking a pointer to a pointer to a struct working from a function parameter?

I'm trying to P/invoke this in such a way I should be able to access the const char* members of this struct from C# (system, game, song, copyright, etc).

This is the struct as it is defined in the C++ header here: gme.h starting at line 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 */
};

In my C# code, I have modeled this struct as follows:

[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;
}

Now, the function I'm calling is one that I have P/Invoked which has the C++ prototype as follows:

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

where gme_err_t is a const char*

(see gme.h, line 74, if you want a direct look at it)

(see gme.cpp , line 252 for its definition)

So, the function without all of its typedefs is as follows:

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

The way this function works is that when called with a valid Music_Emu and a valid track, the result is info about the music track which is assigned to the parameter 'out'.

The const char* being returned is basically for when errors occur, so it's not the main focus. The 'out' parameter is.

I have defined the P/Invoke for this function in C# as follows:

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

Here is my code currently for attempting to read the copyright string in that struct.

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

Any help would be appreciated. I've tried for roughly 4 hours to make this work. I've looked all around StackOverflow (and the net in general) for possible solutions, but I haven't found any that were close to this sort of question. Most other problems were about a pointer to a pointer to a struct of arrays and such, which isn't very helpful at all for this case.

If any other information is needed, just ask, I'd be happy to provide it.

Your trackInfo parameter should be an out IntPtr . Then you can marshal it to a C# struct with the Marshal.PtrToStructure method.

IntPtr trackInfoPtr;
NativeMethods.gme_track_info(emuRef, out trackInfoPtr);
gme_info_t trackInfo = (gme_info_t)Marshal.PtrToStructure(trackInfoPtr, typeof(gme_info_t));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM