Pascal function pointer syntax in Island with loadLibrary & GetprocAddress


(kwonus) #1

I am attempting to do LoadLibrary() and GetProcAddress() using Island, but the documentation really doesn’t adequately descript for to define function pointers. It says that the Delphi-like cdecl keyword is supported, but it does’t say where to put it. I tried Delphi syntax, but the compiler yelled at me. Sans the CDECL keyword, I got this to compile (unnecessary logic stripped), but it doesn’t work:

namespace SimpleImperative;

interface

uses
RemObjects.Elements.RTL,
RemObjects.Elements.System;

type
// FUNCTION POINTERS:
FSearch = private function(criteria: String; scope: String): UInt32;
FSummarize = private function(criteria: array of Char; scope: array of Byte): UInt32;
FExport = private function(book: Byte; chapter: Byte; format: byte): UInt32;
FSet = private function(key: array of Char; value: array of Byte): UInt32;
FGet = private function(key: array of Char): array of Char;

type
Interpreter = public class
public
class method Inititialize(sdkDir: String; libname: String): Boolean;
class method Release;
// FUNCTION POINTERS:
private
class var Search: FSearch;
class var Summarize: FSummarize;
class var Export: FExport;
class var SetVal: FSet;
class var GetVal: FGet;
class var Library: rtl.HMODULE;

end;

class method Interpreter.Release;
begin
if Library <> nil
then begin
rtl.FreeLibraryAndExitThread(Library, 0);
Library := nil;
end;
end;

class method Interpreter.Inititialize(sdkDir: String; libname: String): Boolean;
var
proc: rtl.FARPROC;
begin
result := false;

if lib = nil
then begin
	sdk := sdkDir;
	lib := libname;

	var dll := Path.Combine(sdkdir, lib);
	Library := rtl.LoadLibrary(dll);

	if Library <> nil
	then begin
		proc := rtl.GetProcAddress(Library, "search");
		if proc <> nil
			then self.Search := FSearch(proc)
			else self.Search := nil;
		proc := rtl.GetProcAddress(Library, "summarize");
		if proc <> nil
			then self.Summarize := FSummarize(proc)
			else self.Summarize := nil;
		proc := rtl.GetProcAddress(Library, "export");
		if proc <> nil
			then self.Export := FExport(proc)
			else self.Export := nil;
		proc := rtl.GetProcAddress(Library, "set");
		if proc <> nil
			then self.SetVal := FSet(proc)
			else self.SetVal := nil;
		proc := rtl.GetProcAddress(Library, "get");
		if proc <> nil
			then self.GetVal := FGet(proc)
			else self.GetVal := nil;

		result := (Search <> nil);
	end;
end;

end;

end.

— and the C code looks like this (DLLMain, not included here):
#include “stdafx.h”

extern “C” UINT32 search(wchar_t* criteria, wchar_t* scope)
{
return 0;
}


Since I’m authoring both sides (C++ and Pascal), I’m open to the simplest way to get this to work. However, as I am developing a user-extensible library, I don’t want my users to have dependencies on RemObjects toolchain. So something like LoadLibrary() and GetProcAddress() seems ideal to me. I forget the Unix/Mac/Linux equivalents of these calls, but that’s the easy part. I realize that I may need an underscore on _search, but I don’t think that I’m getting that far. It seems that LoadLibrary is failing.


(Friedrich Westermann) #2

The Calling Convention is done via Attributes

 [CallingConvention(CallingConvention.Stdcall)]
FSummarize = private function(criteria: array of Char; scope: array of Byte): UInt32;

(Carlo Kok) #3

The attribute is how you define calling conventions yes. But you want to use ^char instead of strings