如何从函数参数获取P / Invoking指向结构的指针?

时间:2013-05-31 20:23:47

标签: c# .net pinvoke

我正在尝试以这种方式调用它,我应该能够从C#(系统,游戏,歌曲,版权等)访问此结构的const char *成员。

这是结构,因为它在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;
}

现在,我正在调用的函数是我有P / Invoked的函数,它具有C ++原型,如下所示:

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

其中gme_err_tconst 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(以及一般的网络)周围寻找可能的解决方案,但我还没有找到任何接近这类问题的方法。大多数其他问题都是关于指向数组结构的指针的指针,这对于这种情况根本不是很有帮助。

如果需要任何其他信息,请问,我很乐意提供。

1 个答案:

答案 0 :(得分:0)

您的trackInfo参数应为out IntPtr。然后,您可以使用Marshal.PtrToStructure方法将其编组为C#结构。

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