Difference between revisions of "Using Pascal Libraries with .NET and Mono"

From Lazarus wiki
Jump to navigationJump to search
(First draft)
 
(Added "When to use")
Line 163: Line 163:
  
 
Mono will also look for file simplelib.dll -- that's the reason why we renamed the compiled library above on Linux and OS X.
 
Mono will also look for file simplelib.dll -- that's the reason why we renamed the compiled library above on Linux and OS X.
 +
 +
==When to use native libraries with .NET/Mono==
 +
 +
Why not just code everything in VB.NET or C#? There are several situations where this might not be a  good idea:
 +
 +
* When you have a large or complicated Pascal codebase that you don't want to rewrite (and re-debug) in C#.
 +
* When you have native libraries that need to be used by both native and .NET/Mono apps.
 +
* When there are performance reasons (presumably compiled FPC or Delphi native code is faster than the equivalent compiled bytecode run under .NET/Mono).
 +
* When you need low-level operating system access not available easily with .NET/Mono.
 +
* When you need to quickly develop code in a language you're more proficient in for a multi-developer .NET/Mono project.

Revision as of 19:09, 27 May 2006

Introduction

With the .NET framework, Microsoft provided excellent compatibility for "unmanaged" code. While unmanaged code sounds like something wild and dangerous, it just means legacy code in the form of native Windows libraries. The Mono project included similar support for native libraries on Linux and OS X. What this means is that you can create libraries with Free Pascal and use them with .NET apps on Windows and Mono apps on Linux and OS X.

A simple Pascal library

Copy and save this Pascal code to file SimpleLib.pas:

library SimpleLib;

function MySucc(AVal : Int64) : Int64; stdcall;
begin
  Result := System.Succ(AVal);
end;

function MyPred(AVal : Int64) : Int64; stdcall;
begin
  Result := System.Pred(AVal);
end;

exports
{$IFDEF DARWIN}  {OS X entry points}
  MySucc name '_MySucc',
  MyPred name '_MyPred',
{$ENDIF}
  MySucc,
  MyPred;

end.

Note the conditional directive when compiled on OS X (DARWIN). Apparently the OS X dynamic linker looks for library entry points that start with an underscore.

Now compile the library with Free Pascal:

 fpc -Sd SimpleLib.pas

On Windows, this will create file simplelib.dll. On OS X, this will create file libsimplelib.dylib. On Linux, this will create file simplelib.so. On OS X and Linux, rename the compiled library file to simplelib.dll:

 mv libsimplelib.dylib simplelib.dll

A simple VB.NET app

Copy and save this VB.NET code to file TestLib.vb:

Imports System
Imports System.Runtime.InteropServices

Public Class TestLib

  Const SimpLibName = "simplelib.dll"

   'Declare external functions using the DllImport attribute.
  <DllImport(SimpLibName, EntryPoint:="MySucc", _
             CallingConvention:=CallingConvention.StdCall)> _
             Public Shared Function Succ(ByVal AVal As Long) As Long
    End Function

  <DllImport(SimpLibName, EntryPoint:="MyPred", _
             CallingConvention:=CallingConvention.StdCall)> _
             Public Shared Function Pred(ByVal AVal As Long) As Long
    End Function

  Public Shared Sub Main()
  
    Dim TestVal As Long

    Try
      TestVal = 123
      Console.WriteLine("Value is " & TestVal)
      Console.WriteLine("Successor is " & Succ(TestVal))
      Console.WriteLine("Predecessor is " & Pred(TestVal))
    Catch e As Exception
      Console.WriteLine(e)
    End Try

  End Sub  'Main

End Class  'TestLib

If you have the .NET framework installed on Windows, you can compile this code as follows:

 [pathto]vbc TestLib.vb

where [pathto] is the path to the .NET framework (example: c:\windows\microsoft.net\framework\v1.1.4322\ with .NET 1.1). This will create file TestLib.exe.

If you have Mono installed, you can also try compiling this code as follows:

 mbas TestLib.vb

Currently, Mono's VB.NET compiler is only in the alpha stage and won't compile this code. If you get a compile error, try compiling the C# version.

A simple C# app

Here's the equivalent C# code. Copy and save it to file TestLib.cs.

using System;
using System.Runtime.InteropServices;

public class TestLib {
  
  const string SimpLibName = "simplelib.dll";

   //Declare external functions using the DllImport attribute.
  [DllImport(SimpLibName, EntryPoint="MySucc",
             CallingConvention=CallingConvention.StdCall)]
             public static extern long Succ(long AVal);

  [DllImport(SimpLibName, EntryPoint="MyPred", 
             CallingConvention=CallingConvention.StdCall)] 
             public static extern long Pred(long AVal);

  public static void Main()
  {
    long TestVal;

    try
    {
      TestVal = 123;
      Console.WriteLine("Value is " + TestVal);
      Console.WriteLine("Successor is " + Succ(TestVal));
      Console.WriteLine("Predecessor is " + Pred(TestVal));
    }
    catch(Exception e)
    {
      Console.WriteLine(e);
    }
  }
}

With .NET, you can compile it as follows:

 [pathto]csc TestLib.cs

With Mono, you can compile it as follows:

 mcs TestLib.cs

With both .NET and Mono, compiling will create file TestLib.exe.

Running the simple app

With .NET, just run the compiled app as follows:

 testlib

If .NET can find simplelib.dll, the app will output this to the console:

 Value is 123
 Successor is 124
 Predecessor is 122

With Mono, run the compiled app as follows:

 mono testlib.exe

Mono will also look for file simplelib.dll -- that's the reason why we renamed the compiled library above on Linux and OS X.

When to use native libraries with .NET/Mono

Why not just code everything in VB.NET or C#? There are several situations where this might not be a good idea:

  • When you have a large or complicated Pascal codebase that you don't want to rewrite (and re-debug) in C#.
  • When you have native libraries that need to be used by both native and .NET/Mono apps.
  • When there are performance reasons (presumably compiled FPC or Delphi native code is faster than the equivalent compiled bytecode run under .NET/Mono).
  • When you need low-level operating system access not available easily with .NET/Mono.
  • When you need to quickly develop code in a language you're more proficient in for a multi-developer .NET/Mono project.