Пишу плагин на делфи, с integer разобрался:
local ffi = require("ffi")
local lib = ffi.load("getpix.dll")
ffi.cdef[[
__cdecl int getpix(int h, int x, int y);
]]
ffi.cdef[[
//custom struct
struct my_struct{
int x;
int y;
};
//boolean
__cdecl bool getbool();
//string
__cdecl const char* getstr();
//struct
__cdecl const struct my_struct* getstruct();
]]
спасибо большое.
Если не трудно, почему не могу добиться простого ответа от плагина:
подключаю длл и функцию:
local ffi = require("ffi")
local file = ffi.load("files.dll")
ffi.cdef[[
__cdecl const char* fexists(const char* patch);
]]
function fexists(patch:string):string; cdecl;
begin
fexists := patch;
end;
local patch = 'abc'
local t = file.writef(patch)
log(t)
Не вижу вызова fexists()
--lua
log("clear")
local ffi = require("ffi")
local file = ffi.load("files.dll")
ffi.cdef[[
__cdecl int fexists(int patch);
]]
local patch = 55
local t = file.fexists(patch)
log(t)
library files;
uses
windows,
Classes,
SysUtils;
type
tInitStruct = packed record
FunctionCount : Cardinal;
FunctionNames : Array of Pchar;
end;
tParamStruct = packed record
WindowHandle : Cardinal; // Handle of workWindow
WindowPID : Cardinal; // pid of process of workWindow
Reserved : Cardinal;
ParamString : Pchar; // string of parameters with substituted variables
ParamStringOrig : Pchar; // original string of parameters
Result : array [0..32767] of char // array for returned values
end;
var
ParamStruct: ^tParamStruct; // init by UOPilot
InitStruct : tInitStruct; // init by plugin, free on unload
function InitPlugin(App, Scr: integer; Var Version: Real):Pointer; stdcall;
// App: Application.Handle of UOPilot
// Scr: reserved
begin
// check UOPilot version, if it needed
if Version >= 2.18 then begin
// exported function count, for UOPilot
InitStruct.FunctionCount := 1;
setlength (InitStruct.FunctionNames, InitStruct.FunctionCount);
// exported function names
InitStruct.FunctionNames[0] := 'fexists'
end else
InitStruct.FunctionCount := 0;
// if exported function count = 0, then plugin will be unloaded
Result := @InitStruct;
end;
function fexists(patch:integer):integer; cdecl;
begin
fexists := patch;
end;
procedure DonePlugin; stdcall;
begin
// free memory
setlength (InitStruct.FunctionNames, 0);
end;
// exported function example
Exports
InitPlugin,
DonePlugin,
fexists;
begin
end.
--lua
log("clear")
local ffi = require("ffi")
local file = ffi.load("files.dll")
ffi.cdef[[
__cdecl const char* fexists(const char* patch);
]]
local patch = "55"
local t = file.fexists(patch)
log(t)
library files;
uses
windows,
Classes,
SysUtils;
type
tInitStruct = packed record
FunctionCount : Cardinal;
FunctionNames : Array of Pchar;
end;
tParamStruct = packed record
WindowHandle : Cardinal; // Handle of workWindow
WindowPID : Cardinal; // pid of process of workWindow
Reserved : Cardinal;
ParamString : Pchar; // string of parameters with substituted variables
ParamStringOrig : Pchar; // original string of parameters
Result : array [0..32767] of char // array for returned values
end;
var
ParamStruct: ^tParamStruct; // init by UOPilot
InitStruct : tInitStruct; // init by plugin, free on unload
function InitPlugin(App, Scr: integer; Var Version: Real):Pointer; stdcall;
// App: Application.Handle of UOPilot
// Scr: reserved
begin
// check UOPilot version, if it needed
if Version >= 2.18 then begin
// exported function count, for UOPilot
InitStruct.FunctionCount := 1;
setlength (InitStruct.FunctionNames, InitStruct.FunctionCount);
// exported function names
InitStruct.FunctionNames[0] := 'fexists'
end else
InitStruct.FunctionCount := 1;
// if exported function count = 0, then plugin will be unloaded
Result := @InitStruct;
end;
function fexists(patch:string):string; cdecl;
begin
fexists := patch;
end;
procedure DonePlugin; stdcall;
begin
// free memory
setlength (InitStruct.FunctionNames, 0);
end;
// exported function example
Exports
InitPlugin,
DonePlugin,
fexists;
begin
end.
1) Если не планируется поддержка системы плагинов пилота (т.е. не ffi), то можно оставить только fexists(). InitPlugin, DonePlugin и структуры убрать.
2) Момент со строками:
function fexists(patch:string):string; cdecl;
begin
fexists := patch;
end;
function fexists(patch:PChar):PChar; cdecl;
begin
fexists := patch;
end;
function fexists(patch:PChar):PChar; cdecl;
var
plugin_str: string;
begin
plugin_str := 'plugin string';
fexists := Addr(plugin_str[1]);
end;
--lua
local ffi = require("ffi")
log "clear" log "mode compact"
local buf = ffi.new('char[999]') -- выделить 999 байт
log(tostring(buf))
log('Размер в байтах: ' .. ffi.sizeof(buf))
ffi.copy(buf, 'Текст') -- записать нужный текст
-- в длл передаём buf и его размер, читаем/пишем, делаем что надо
log(ffi.string(buf))
Файлы как пример. Смысл в том, что плагин пишет(в моем примере читает файл) в уже выделенный кусок через ffi, а не возвращает сам.
не раз возвращаюсь к этому топику, и не могу добиться результата. вот к примету со структурой (возврат более 2 и более значений из функции.) допустим, необходимо вернуть не одно число, а координаты:
Нужно в скрипте объявить структуру и передать в функцию её адрес. В функции записывать данные.
--lua
local ffi = require('ffi')
local lib = ffi.load('PilotDLL.dll') -- длл должна быть в папке с пилотом
ffi.cdef[[
typedef struct { int a; int b; } MyStruct;
__declspec(dllexport)void testf( MyStruct *result, int a, int b );
]]
log 'clear' log 'mode compact'
local result = ffi.new('MyStruct') -- объявили структуру
lib.testf( result, 100, 20 ) -- вызов функции
log(result.a) -- вернёт 2000 (100 * 20)
log(result.b) -- вернёт 5 (100 / 20)
#include "pch.h"
struct my_struct {
int x;
int y;
};
extern "C" __declspec(dllexport)void testf(struct my_struct *r, int a, int b)
{
r->x = a * b;
r->y = a / b;
}
ура, работает и с делфи)
--lua
local ffi = require('ffi')
local lib = ffi.load('Project1.dll') -- длл должна быть в папке с пилотом
ffi.cdef[[
typedef struct { int a; int b; } MyStruct;
__cdecl void testf( MyStruct *result, int a, int b );
]]
log 'clear' log 'mode compact'
local result = ffi.new('MyStruct') -- объявили структуру
lib.testf( result, 100, 20 ) -- вызов функции
log(result.a) -- вернёт 2000 (100 * 20)
log(result.b) -- вернёт 5 (100 / 20)
Library project1;
uses
SysUtils,
Classes;
Type
TMyStruct = Record
x: Integer;
y: Integer;
End;
procedure testf(Var r: TMyStruct; a: Integer; b: Integer); Cdecl;
Begin
r.x := a * b;
r.y := a div b;
End;
Exports
testf;
Begin
End.
Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)