Results 1 to 8 of 8

Thread: Need help accessing a FreePascal-created library

  1. #1

    Need help accessing a FreePascal-created library

    Hi all,
    I've been experimenting with creating a dynamic library from my game engine in the last couple of days. The reason is some developers are interested in my game engine, but would rather use it with C/C++ or C#.
    And the more important reason is that I have the course "Game Development" this semester at school where we have to use Horde3D and C++. For our final project I want to use my own sprite and font manager since Horde3D's built-in overlays are not really satisfying (just supports stretchting; no rotating, coloring or alpha) for my purposes and I really would love to have TTF support in my game instead of just the one TGA font that comes with the default project we have to use.

    My plan is to flatten down my object-orientiented design so it can be used C or C# and then create classes on the top of that for C++ and C#.
    I already tried porting the classes I needed from Object Pascal to C++ which unfortunately didn't work as planned and I hope creating a dynamic library and writing a C header would be much easier and less painful.

    Allright, generating the library works without any problems, but when I try to access to the library with C# or C I get some strange results.

    Let's take this code for example:
    [pascal]
    library SDLTestLib;

    uses
    SDL;

    var
    MainSurface: PSDL_Surface;

    procedure Initialize();
    begin
    SDL_Init(SDL_INIT_VIDEO);
    end;

    procedure Finalize();
    begin
    SDL_Quit;
    end;

    procedure CreateWindow(Width: Integer; Height: Integer; BPP: Integer);
    begin
    MainSurface := SDL_SetVideoMode(Width, Height, BPP, SDL_SWSURFACE);
    if not Assigned(MainSurface) then WriteLn('Something isn''t right here.');
    end;

    procedure SetWindowCaption(Caption: PChar);
    begin
    SDL_WM_SetCaption(Caption, Caption);
    end;

    procedure Flip;
    begin
    SDL_Flip(MainSurface);
    end;

    exports
    {$IFDEF DARWIN} {OS X entry points}
    Initialize name '_Initialize',
    Finalize name '_Finalize',
    CreateWindow name '_CreateWindow',
    SetWindowCaption name '_SetWindowCaption',
    Flip name '_Flip',
    {$ENDIF}
    Initialize,
    Finalize,
    CreateWindow,
    SetWindowCaption,
    Flip;

    end.
    [/pascal]

    My C header:
    Code:
    #ifndef _SDLTESTLIB_H_
    #define _SDLTESTLIB_H_
    
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    extern void Initialize();
    extern void Finalize();
    extern void CreateWindow(int Width, int Height, int BPP);
    extern void Flip();
    extern void SetWindowCaption(char* caption);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif /* _SDLTESTLIB_H_ */
    My C# file:
    Code:
    using System;
    using System.Runtime.InteropServices;
    
    public class SDLTestLib {
     
     const string ElysionLibName = "SDLTestLib.dll";
    
     [DllImport(ElysionLibName, EntryPoint="Initialize",
           CallingConvention=CallingConvention.StdCall)]
           public static extern void Initialize();
     
     [DllImport(ElysionLibName, EntryPoint="Finalize",
           CallingConvention=CallingConvention.StdCall)]
           public static extern void Finalize();
    
     [DllImport(ElysionLibName, EntryPoint="Flip", 
           CallingConvention=CallingConvention.StdCall)] 
           public static extern void Flip();
     
     [DllImport(ElysionLibName, EntryPoint="CreateWindow",
           CallingConvention=CallingConvention.StdCall)]
           public static extern void CreateWindow(int Width, int Height, int BPP);
     
     [DllImport(ElysionLibName, EntryPoint="SetWindowCaption", 
           CallingConvention=CallingConvention.StdCall)] 
           public static extern void SetWindowCaption(string caption);
    
     public static void Main()
     {
      bool done = false;
     
    	Initialize();
    	Console.WriteLine("SDL initialized.");
     
    	CreateWindow(640, 480, 16);
    	Console.WriteLine("Window created.");
      
      while (!done)
      {
      	Flip();	
      }
    	
    	Finalize();
     }
    }
    The C# version won't work and terminates with an access violation when calling the Flip-procedure. The C version works, but assumes the Bits value as the height.
    Oddly enough, if I change the code to interface with GLFW instead of SDL, the C# version works, but assigns the height value to the width.

    I'm using FreePascal 2.4.0/2.4.1, tested with Windows XP (virtual machine) and Windows Vista.
    Anyone had similar problems? What am I doing wrong? When writing a pascal header for C-DLL, you need something like
    Code:
    {$MINENUMSIZE 4}
    {$PACKRECORDS C}
    {$H+}
    {$MACRO ON}
    in the Pascal header. Do I need something similar in my Pascal library or in C/C# header? Is there something so obvious, I may have overlooked it?
    Freeze Development | Elysion Game Framework | Twitter: @Stoney_FD
    Check out my new book: Irrlicht 1.7.1 Realtime 3D Engine Beginner's Guide (It's C++ flavored though)

    Programmer: A device for converting coffein into software.

  2. #2

    Re: Need help accessing a FreePascal-created library

    if you want to access a pascal lib from c, you might need to use the "cdecl" calling convention for your pascal routines.

    Or maybe "stdcall"

    Not sure about C# though...

    cheers,
    Paul

  3. #3

    Re: Need help accessing a FreePascal-created library

    Thanks Paul for the cdecl/stdcall tip.
    I could have thought of that

    Unfortunately that was not the solution, it's still not working.

    As for C#, it's already called with stdcall (CallingConvention = CallingConvention.StdCall), I changed it to Cdecl, but no change there either.
    Freeze Development | Elysion Game Framework | Twitter: @Stoney_FD
    Check out my new book: Irrlicht 1.7.1 Realtime 3D Engine Beginner's Guide (It's C++ flavored though)

    Programmer: A device for converting coffein into software.

  4. #4

    Re: Need help accessing a FreePascal-created library

    Did you add the cdecl or stdcall directive in the pascal code too?

    The default is most likely fastcall which is not supported in neither C or C#
    Peregrinus, expectavi pedes meos in cymbalis
    Nullus norvegicorum sole urinat

  5. #5

    Re: Need help accessing a FreePascal-created library

    Quote Originally Posted by JSoftware
    Did you add the cdecl or stdcall directive in the pascal code too?

    The default is most likely fastcall which is not supported in neither C or C#
    Sorry, but as JSoftware said, that was what I meant when I said to add the cdecl or stdcall to your pascal libs.

    Like this:

    [pascal]library SDLTestLib;

    uses
    SDL;

    var
    MainSurface: PSDL_Surface;

    procedure Initialize(); cdecl
    begin
    SDL_Init(SDL_INIT_VIDEO);
    end;

    procedure Finalize(); cdecl
    begin
    SDL_Quit;
    end;

    procedure CreateWindow(Width: Integer; Height: Integer; BPP: Integer); cdecl
    begin
    MainSurface := SDL_SetVideoMode(Width, Height, BPP, SDL_SWSURFACE);
    if not Assigned(MainSurface) then WriteLn('Something isn''t right here.');
    end;

    procedure SetWindowCaption(Caption: PChar); cdecl
    begin
    SDL_WM_SetCaption(Caption, Caption);
    end;

    procedure Flip; cdecl
    begin
    SDL_Flip(MainSurface);
    end;

    exports
    {$IFDEF DARWIN} {OS X entry points}
    Initialize name '_Initialize',
    Finalize name '_Finalize',
    CreateWindow name '_CreateWindow',
    SetWindowCaption name '_SetWindowCaption',
    Flip name '_Flip',
    {$ENDIF}
    Initialize,
    Finalize,
    CreateWindow,
    SetWindowCaption,
    Flip;

    end.
    [/pascal]

    Try something like above - see modified routines with cdecl added after...

    If this doesn't work, try stdcall instead

    cheers,
    Paul

  6. #6

    Re: Need help accessing a FreePascal-created library

    Thank you both, works like a charm now.
    Freeze Development | Elysion Game Framework | Twitter: @Stoney_FD
    Check out my new book: Irrlicht 1.7.1 Realtime 3D Engine Beginner's Guide (It's C++ flavored though)

    Programmer: A device for converting coffein into software.

  7. #7

    Re: Need help accessing a FreePascal-created library

    Quote Originally Posted by Stoney
    Thank you both, works like a charm now.
    Yay!
    Just glad I could help

    So was cdecl the 'charm', or was it 'stdcall'?

    cheers,
    Paul

  8. #8

    Re: Need help accessing a FreePascal-created library

    It was cdecl in my case.
    Would have probably worked with stdcall also, but since cdecl worked, I haven't tried stdcall.
    Freeze Development | Elysion Game Framework | Twitter: @Stoney_FD
    Check out my new book: Irrlicht 1.7.1 Realtime 3D Engine Beginner's Guide (It's C++ flavored though)

    Programmer: A device for converting coffein into software.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •