Numerics 0.55 released

0

Numerics 0.55 is available for download

The main improvements are:

1) Explicit DLL load is supported by the function

function LoadNumerics(const Name: string = ''): TF_RESULT;

and this is now the recommended method to load the dll because it enables error handling:

if LoadNumerics() < 0 then
  raise Exception.Create('!!! - DLL load error');

if the LoadNumerics was not called the dll is loaded transparently when needed.

2) More BigInteger functions implemented:

2.1) Integer square root:

    class function Sqrt(A: BigInteger): BigInteger; static;

2.2) Euclid algorithm (aka Greatest Common Divisor) and Extended Euclid algorithm:

    class function GCD(A, B: BigInteger): BigInteger; static;
    class function EGCD(A, B: BigInteger; var X, Y: BigInteger): BigInteger; static;

2.3) Modular arithmetic:

    class function ModPow(const BaseValue, ExpValue, Modulo: BigInteger): BigInteger; static;
    class function ModInverse(A, Modulo: BigInteger): BigInteger; static;

Most of the above functions were written while I was doing the programming assignments of the Coursera Cryptography 1 course by prof. Dan Boneh. It was fun to use my own BigInteger implementation.

3) C++ support added. I used free CodeBlocks IDE to port the PiBench console application to C++.

Merry Christmas and Happy New Year!

Advertisements

Consuming Delphi interfaces in Dephi and C++

5

An object-oriented DLL written in Delphi exports functions with parameters of interface type. A code consuming such DLL can use an interface reference directly, but a better way is to write a wrapper type which encapsulates an interface reference. Let us consider as an example a simple interface IBytes designed to work with byte arrays:

unit ITypes;

interface

type
  IBytes = interface
    function GetLength: Integer; stdcall;
    procedure Append(B: Byte); stdcall;
    procedure CopyTo(var C: IBytes); stdcall;
  end;

implementation

end.

The IBytes interface is implemented by the TByteObject class:

unit ByteObjects;

interface

uses ITypes;

type
  TByteObject = class(TInterfacedObject, IBytes)
    FBytes: array of Byte;
    function GetLength: Integer; stdcall;
    procedure Append(B: Byte); stdcall;
    procedure CopyTo(var C: IBytes); stdcall;
  end;

implementation

{ TByteObject }

procedure TByteObject.Append(B: Byte);
begin
  SetLength(FBytes, Length(FBytes) + 1);
  FBytes[Length(FBytes)]:= B;
end;

procedure TByteObject.CopyTo(var C: IBytes);
var
  Instance: TByteObject;

begin
  Instance:= TByteObject.Create;
  SetLength(Instance.FBytes, Length(FBytes));
  Move(Pointer(FBytes)^, Pointer(Instance.FBytes)^, Length(FBytes));
  C:= Instance;
end;

function TByteObject.GetLength: Integer;
begin
  Result:= Length(FBytes);
end;

end.

We implement the IBytes interface in DLL:

library TestDLL;

uses
  SysUtils,
  Classes,
  ITypes in 'ITypes.pas',
  ByteObjects in 'ByteObjects.pas';

procedure GetInterface(var I: IBytes); stdcall;
begin
  I:= TByteObject.Create;
end;

exports
  GetInterface;

{$R *.res}

begin
end.

The DLL exports the single function which creates instances of TByteObject class.

To consume the IBytes interface in Delphi we use an advanced record type to avoid the unnecessary overhead of Delphi classes:

unit ByteWrappers;

interface

uses Windows, ITypes;

type
  TGetInterface = procedure(var I: IBytes); stdcall;

var
  GetInterface: TGetInterface;

function LoadDll(const Name: string): Boolean;

type
  TMyBytes = record
  private
    FBytes: IBytes;
  public
    procedure Append(B: Byte);
    procedure CopyTo(var C: TMyBytes);
    function GetLength: Integer;
    procedure Free;
  end;

implementation

{ TMyBytes }

procedure TMyBytes.Append(B: Byte);
begin
  if (FBytes = nil) then GetInterface(FBytes);
  FBytes.Append(B);
end;

procedure TMyBytes.CopyTo(var C: TMyBytes);
begin
  if (FBytes = nil) then C.FBytes:= nil
  else FBytes.CopyTo(C.FBytes);
end;

procedure TMyBytes.Free;
begin
  FBytes:= nil;
end;

function TMyBytes.GetLength: Integer;
begin
  if (FBytes = nil) then Result:= 0
  else Result:= FBytes.GetLength;
end;

function LoadDll(const Name: string): Boolean;
var
  LibHandle: THandle;

begin
  LibHandle:= LoadLibrary(PChar(Name));
  if (LibHandle <> 0) then begin
    @GetInterface:= GetProcAddress(LibHandle, 'GetInterface');
    if @GetInterface <> nil then begin
      Result:= True;
      Exit;
    end;
    FreeLibrary(LibHandle);
  end;
  Result:= False;
end;

end.

And simple test application to be sure everything works as expected:

program Test;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  ITypes in 'ITypes.pas',
  ByteWrappers in 'ByteWrappers.pas';

procedure TestInterface;
var
  Bytes1, Bytes2: TMyBytes;

begin
  Bytes1.Append(0);
  Bytes1.CopyTo(Bytes2);
  Bytes1.Append(0);
  Writeln(Bytes1.GetLength, ' -- ', Bytes2.GetLength);
end;

begin
  try
    ReportMemoryLeaksOnShutdown:= True;
    if LoadDll('TestDLL.dll')
      then TestInterface
      else Writeln('Can''t load TestDLL.dll');
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

So far so good; now we want to consume the above Delphi interface in a C++ structure (or a class – there is no difference between a C++ structure and a C++ class here). The solution is:

// ByteWrappers.hpp
#ifndef BYTEWRAPPERS_H_INCLUDED
#define BYTEWRAPPERS_H_INCLUDED

#include <string>

using namespace std;

typedef uint8_t Byte;
typedef int32_t Integer;

bool LoadDll(string Name);

class IBytes {
  public:
    virtual Integer __stdcall QueryInterface(void* riid, void** ppvObject) = 0;
    virtual Integer __stdcall AddRef() = 0;
    virtual Integer __stdcall Release() = 0;
    virtual Integer __stdcall GetLength() = 0;
    virtual void __stdcall Append(Byte B) = 0;
    virtual void __stdcall CopyTo(IBytes** C) = 0;
};

class MyBytes {
  private:
    IBytes* FBytes;
  public:
    MyBytes() : FBytes(NULL) {};    // default constructor
    MyBytes(const MyBytes& A)       // copy constructor
    {
    	FBytes = A.FBytes;
    	if (FBytes != NULL)
    	{
    		FBytes->AddRef();
    	}
    };

    ~MyBytes()                      // destructor
    {
  	    if (FBytes != NULL)
  	    {
  		    FBytes->Release();
  		    FBytes = NULL;
  	    }
    };

    MyBytes& operator= (const MyBytes& A)   // assignment
    {
        if (A.FBytes != NULL)
            A.FBytes->AddRef();
        if (FBytes != NULL)
            FBytes->Release();
        FBytes = A.FBytes;
        return *this;
    }

    void Free()
    {
        if (FBytes != NULL)
        {
            FBytes->Release();
            FBytes = NULL;
        }
    }

    void Append(Byte B);
    void CopyTo(MyBytes& C);
    Integer GetLength();
};

#endif // BYTEWRAPPERS_H_INCLUDED
// ByteWrappers.cpp
#include <windows.h>
#include "ByteWrappers.hpp"

typedef void(__stdcall *PGetInterface)(IBytes**);
PGetInterface GetInterface = 0;

void MyBytes::Append(Byte B)
{
    if (FBytes == NULL) GetInterface(&FBytes);
    FBytes->Append(B);
}

void MyBytes::CopyTo(MyBytes& C)
{
    if (FBytes == NULL) C.Free();
    else FBytes->CopyTo(&C.FBytes);
}

Integer MyBytes::GetLength()
{
    if (FBytes == NULL) return 0;
    else return FBytes->GetLength();
}

bool LoadDll(string Name)
{
    HINSTANCE LibHandle;

    LibHandle = LoadLibrary(Name.c_str());
    if (LibHandle != 0)
    {
        GetInterface = (PGetInterface)GetProcAddress(LibHandle, "GetInterface");
        if (GetInterface != NULL) return true;
        FreeLibrary(LibHandle);
    }
    return false;
}

Test application:

#include <iostream>
#include <string>
#include "ByteWrappers.hpp"

using namespace std;

void TestInterface(){
    MyBytes Bytes1;
    MyBytes Bytes2;

    Bytes1.Append(0);
    Bytes1.CopyTo(Bytes2);
    Bytes1.Append(0);
    cout << Bytes1.GetLength() << " -- " << Bytes2.GetLength() << endl;
}

int main()
{
    if (LoadDll("TestDLL.dll"))
        TestInterface();
    else
        cout << "Can't load TestDLL.dll" << endl;
    return 0;
}

Some details worth being mentioned:

  • Delphi interfaces are always derived from IUnknown; a corresponding pure abstract C++ class should also define IUnknown methods;
  • Delphi interface type is kind of a pointer to the corresponding C++ abstract class, so sometimes we need one more level of indirection in C++ code;
  • Delphi interface variables are always initialized to nil by the compiler; in C++ we need default constructor to implement the nil-initialization;
  • Delphi interfaces are automatically released (i.e. call IUnknown._Release method) when an interface variable goes out of scope; In C++ we implement the same functionality in destructor;
  • Interface assignment in Delphi implicitly calls _Addref and _Release methods of IUnknown; in C++ we overload the assignment operator to implement the interface assignment correctly;
  • C++ supports variable initialization like this:
        MyBytes Bytes1;
        Bytes1.Append(0);
        MyBytes Bytes2 = Bytes1;
    

    to implement it correctly in our case we need a copy constructor.

Operator Overloading in Delphi and C++

1

Let us consider the following toy problem: implement a user-defined integer type MyInt which is assignment compatible with built-in signed and unsigned integers and supports addition. We assume here that all integers are 32-bit. Assigning unsigned integers above 0x7fffffff to MyInt and assigning negative MyInt values to unsigned integers should raise exceptions.

To begin with we have a record (Delphi)

type
  MyInt = record
  private
    FValue: Integer;
  end;

or structure (C++)

struct MyInt{
private:
  int FValue;
};

By convention we use explicit conversion if a conversion can raise exception and implicit conversion otherwise. The Delphi solution is straightforward:

unit MyInts;

interface

uses SysUtils;

type
  MyInt = record
  private
    FValue: Integer;
  public
    class operator Implicit(AValue: MyInt): Integer;
    class operator Explicit(AValue: MyInt): Cardinal;
    class operator Implicit(AValue: Integer): MyInt;
    class operator Explicit(AValue: Cardinal): MyInt;
    class operator Add(A, B: MyInt): MyInt;
  end;

implementation

class operator MyInt.Explicit(AValue: MyInt): Cardinal;
begin
  if AValue.FValue < 0 then
    raise Exception.Create(IntToStr(AValue.FValue));
  Result:= AValue.FValue;
end;

class operator MyInt.Explicit(AValue: Cardinal): MyInt;
begin
  if AValue > $7FFFFFFF then
    raise Exception.Create(IntToStr(AValue));
  Result.FValue:= AValue;
end;

class operator MyInt.Implicit(AValue: MyInt): Integer;
begin
  Result:= AValue.FValue;
end;

class operator MyInt.Implicit(AValue: Integer): MyInt;
begin
  Result.FValue:= AValue;
end;

class operator MyInt.Add(A, B: MyInt): MyInt;
begin
  Result.FValue:= A.FValue + B.FValue;
end;

end.

With C++ we need more to take into account. First C++ supports copy initialization

  MyInt M = 1;

which is implemented by a constructor while a plain assignment requires either a conversion operator

  MyInt M;
  M = 1;

or an assignment operator

  MyInt M = 1;
  MyInt M1;
  M1 = M;

If we do not declare an assignment operator C++ implicitly provides the one which implements assignment by shallow coping; it is enough for our problem.

Second we have 2 possible ways to implement the addition operator – as a member function or as a plain function. The member function treats the operands of a binary operation asymmetrically – the first operand is passed as this pointer (different from Delphi which implements the operator member function as static) – and rarely used. More common is to implement a binary operation by a plain function which should be declared as friend in MyInt structure to enable access to the private field FValue.

Third the conversion operators in C++ are “one-way”. We can define the conversion operator FROM MyInt; conversion TO MyInt is implemented by a constructor.

There are more language details a C++ programmer should have in mind while implementing operator overloading; you will discover them if you start experimenting with the code. I leave them out of the article.

Putting it all together we are coming to the following code:

(MyInts.hpp)

#ifndef MYINTS_HPP_INCLUDED
#define MYINTS_HPP_INCLUDED

struct MyInt{
private:
    int FValue;
public:
    MyInt(int A = 0);
    MyInt(unsigned int A);
    MyInt(const MyInt& A);
//    MyInt operator=(MyInt A);

    operator int();
    operator unsigned int();
    friend MyInt operator+(const MyInt& A, const MyInt& B);
};

#endif // MYINTS_HPP_INCLUDED

(MyInts.cpp)

#include <iostream>
#include "MyInts.hpp"

using namespace std;

MyInt::MyInt(int A){
    cout << "hello from MyInt(int) ctor" << endl;
    FValue = A;
}

MyInt::MyInt(unsigned int A){
    cout << "hello from MyInt(unsigned int A) ctor" << endl;
    if (A > 0x7fffffff){
        cout << "throwing " << A << endl;
        throw(A);
    }
    FValue = A;
}

MyInt::MyInt(const MyInt& A){
    cout << "hello from MyInt(const MyInt&) ctor" << endl;
    FValue = A.FValue;
}

/*
MyInt MyInt::operator=(MyInt A){
    cout << "hello from assignment operator" << endl;
    FValue = A.FValue;
    return *this;
}
*/

MyInt::operator int(){
    cout << "hello from int conversion operator" << endl;
    return FValue;
}

MyInt::operator unsigned int(){
    cout << "hello from unsigned int conversion operator" << endl;
    if (FValue < 0){
        cout << "throwing " << FValue << endl;
        throw(FValue);
    }
    return FValue;
}

MyInt operator+(const MyInt& A, const MyInt& B){
    cout << "hello from addition operator" << endl;
    MyInt Result = A.FValue + B.FValue;
    return Result;
}

On the Pointers and References

6

A Reference is a distinct concept in C/C++ languages. The next code sample (MinGW GCC compiler was used)

#include <iostream>

int main()
  {
    int Value;
    int &ValueRef = Value;

    Value = 2;
    std::cout << "Value: " << Value << "\n";
    std::cout << "ValueRef: " << ValueRef << "\n";

    ValueRef = 3;
    std::cout << "Value: " << Value << "\n";
    std::cout << "ValueRef: " << ValueRef << "\n";
    return 0;
  }

declares ValueRef as a reference to Value variable. The output is
_ref1
Though ValueRef variable is a pointer to Value internally the indirection operator is never used, and the syntax for accessing Value directly or indirectly via ValueRef is the same. ValueRef is also called an alias to Value; the point that ValueRef variable is a pointer internally is just an implementation detail.

Another important thing about C/C++ references is that they are always initialized. The language syntax enforces that you cannot declare a wild reference.

Pascal does not have the same reference concept. The closest concept is a procedure parameter passed by reference:

program ref;

{$APPTYPE CONSOLE}

var
  Value: Integer;

procedure Test(var ValueRef: Integer);
begin
  Writeln('ValueRef: ', ValueRef);
  ValueRef:= 3;
end;

begin
  Value:= 2;
  Writeln('Value: ', Value);
  Test(Value);

  Writeln('Value: ', Value);
  Test(Value);
end.

we can see that

  • ValueRef does not use indirection operator to access a referenced variable;
  • the language syntax enforces that ValueRef is always initialized.

Delphi does not elaborate the reference concept, though there are many built-in types in the language that are ‘transparent pointers’ – objects, interfaces, dynamic arrays, strings. The term reference can be used for example for object variables because the language syntax makes these variables indistinguishable from referenced instances. Instead the term object is usually used, that can mean object reference or object instance, so sometimes you think twice to understand what a particular object does mean.