views:

124

answers:

1

I'm trying to access some Ghostscript functions like so:

[DllImport(@"C:\Program Files\GPLGS\gsdll32.dll", EntryPoint = "gsapi_revision")]
public static extern int Foo(gsapi_revision_t x, int len);

public struct gsapi_revision_t
{
    [MarshalAs(UnmanagedType.LPTStr)]
    string product;

    [MarshalAs(UnmanagedType.LPTStr)]
    string copyright;


    long revision;
    long revisiondate;
}

public static void Main()
{
    gsapi_revision_t foo = new gsapi_revision_t();
    Foo(foo, Marshal.SizeOf(foo));

This corresponds with these definitions from the iapi.h header from ghostscript:

typedef struct gsapi_revision_s {
    const char *product;
    const char *copyright;
    long revision;
    long revisiondate;
} gsapi_revision_t;

GSDLLEXPORT int GSDLLAPI 
gsapi_revision(gsapi_revision_t *pr, int len);

But my code is reading nothing into the string fields. If I add 'ref' to the function, it reads gibberish. However, the following code reads in the data just fine:

public struct gsapi_revision_t
{
    IntPtr product;
    IntPtr copyright;

    long revision;
    long revisiondate;
}

public static void Main()
{
    gsapi_revision_t foo = new gsapi_revision_t();

    IntPtr x = Marshal.AllocHGlobal(20);
    for (int i = 0; i < 20; i++)
        Marshal.WriteInt32(x, i, 0);

    int result = Foo(x, 20);
    IntPtr productNamePtr = Marshal.ReadIntPtr(x);
    IntPtr copyrightPtr = Marshal.ReadIntPtr(x, 4);
    long revision = Marshal.ReadInt64(x, 8);
    long revisionDate = Marshal.ReadInt64(x, 12);

    byte[] dest = new byte[1000];
    Marshal.Copy(productNamePtr, dest, 0, 1000);


    string name = Read(productNamePtr);
    string copyright = Read(copyrightPtr);
}

    public static string Read(IntPtr p)
    {
        List<byte> bits = new List<byte>();
        int i = 0;

        while (true)
        {
            byte b = Marshal.ReadByte(new IntPtr(p.ToInt64() + i));
            if (b == 0)
                break;

            bits.Add(b);
            i++;
        }

        return Encoding.ASCII.GetString(bits.ToArray());
    }

So what am I doing wrong with marshaling?

+1  A: 

UnmanagedType.LPTStr is platform dependent (ANSI on Win98, Unicode on NT/XP). Your C++ structure uses the char * type, so you probably want UnmanagedType.LPStr instead.

Also, a long in C# is 64 bits while a long in C++ is 32 bits. You probably want to use int in your C# code.

GBegen
Oh, so simple. Thank you.
yodaj007