powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Передача аннонимной функции в cи библиотеку
25 сообщений из 53, страница 1 из 3
Передача аннонимной функции в cи библиотеку
    #39787893
Foxpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имеется
Код: plaintext
1.
 size_t (*write)(const char *str, size_t len); // Тут менялись соглашения о вызове. 



Всё хорошо, пока не назначить анонимную функцию delphi
Код: pascal
1.
2.
3.
4.
5.
 Engine.write:= 
 function(const str: PAnsiChar; len: size_t): size_t cdecl // Тут были перечислены все соглашения. Но по стандарту должен cdecl  
 begin
   // Тут код никогда не выполняется
 end;




Код: pascal
1.
2.
3.
 Twrite =  function(const str: PAnsiChar; len: size_t): size_t cdecl; // Так работает для присвоение Си но НЕ работает для Delphi

 Twrite =  reference to function(const str: PAnsiChar; len: size_t): size_t cdecl; // Вот так, НЕ работает для СИ, но работает для Delphi



Анонимные функции это вообще что??? Мне казалось что это обычная функция, только анонимная.

Обычная функция
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
005D080F 33C0             xor eax,eax
005D0811 55               push ebp
005D0812 6860085D00       push $005d0860
005D0817 64FF30           push dword ptr fs:[eax]
005D081A 648920           mov fs:[eax],esp
Project1.dpr.18: write(UTF8String(str));
005D081D 8D45F8           lea eax,[ebp-$08]
005D0820 8B5508           mov edx,[ebp+$08]
005D0823 B9E9FD0000       mov ecx,$0000fde9
005D0828 E8FBA9E3FF       call @LStrFromPChar
005D082D 8B55F8           mov edx,[ebp-$08]
005D0830 A1A8EB5D00       mov eax,[$005deba8]
005D0835 E80A7EE3FF       call @Write0LString
005D083A E83D73E3FF       call @Flush
005D083F E8E867E3FF       call @_IOTest
Project1.dpr.19: Result := len;
005D0844 8B450C           mov eax,[ebp+$0c]
005D0847 8945FC           mov [ebp-$04],eax
Project1.dpr.20: end;
005D084A 33C0             xor eax,eax
005D084C 5A               pop edx
005D084D 59               pop ecx
005D084E 59               pop ecx
005D084F 648910           mov fs:[eax],edx
005D0852 6867085D00       push $005d0867
005D0857 8D45F8           lea eax,[ebp-$08]
005D085A E8E9A2E3FF       call @LStrClr
005D085F C3               ret 
005D0860 E9DB98E3FF       jmp @HandleFinally
005D0865 EBF0             jmp $005d0857
005D0867 8B45FC           mov eax,[ebp-$04]
005D086A 59               pop ecx
005D086B 59               pop ecx
005D086C 5D               pop ebp
005D086D C3               ret 




Анонимная функция
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
005D0C4F 33C0             xor eax,eax
005D0C51 55               push ebp
005D0C52 68A00C5D00       push $005d0ca0
005D0C57 64FF30           push dword ptr fs:[eax]
005D0C5A 648920           mov fs:[eax],esp
Project1.dpr.93: write(UTF8String(str));
005D0C5D 8D45F8           lea eax,[ebp-$08]
005D0C60 8B550C           mov edx,[ebp+$0c]
005D0C63 B9E9FD0000       mov ecx,$0000fde9
005D0C68 E8BBA5E3FF       call @LStrFromPChar
005D0C6D 8B55F8           mov edx,[ebp-$08]
005D0C70 A1A8EB5D00       mov eax,[$005deba8]
005D0C75 E8CA79E3FF       call @Write0LString
005D0C7A E8FD6EE3FF       call @Flush
005D0C7F E8A863E3FF       call @_IOTest
Project1.dpr.94: Result := len;
005D0C84 8B4510           mov eax,[ebp+$10]
005D0C87 8945FC           mov [ebp-$04],eax
Project1.dpr.95: end;
005D0C8A 33C0             xor eax,eax
005D0C8C 5A               pop edx
005D0C8D 59               pop ecx
005D0C8E 59               pop ecx
005D0C8F 648910           mov fs:[eax],edx
005D0C92 68A70C5D00       push $005d0ca7
005D0C97 8D45F8           lea eax,[ebp-$08]
005D0C9A E8A99EE3FF       call @LStrClr
005D0C9F C3               ret 



Это если вызвать из Delphi кода. А если вызвать из СИ то вываливается в av даже не вызвав функцию по адресу

... Может быть так что этот адрес известен только для Delphi ? А СИ менеджер памяти о нём совершенно ничего не знает?
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39787911
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FoxpcАнонимные функции это вообще что???
Анонимная функция это интерфейс с методом Invoke.
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39787944
Foxpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Kazantsev Alexey,

Простыми словами, вызвать анонимную функцию из сей не получится. А жаль.. Удобно было бы пилить вложенные функции, не разбрасывая их по пространству. Так как запихав их в класс, то после вызова метод класса не знает ничего о классе. Это не TMethod
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39787964
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Foxpc,

а зачем конкретно этим методам "знать что-то о классе", а тем более об объекте ?

делай в классе статические КЛАССОВЫЕ методы, они по сути глобальные функции скрытые из глобального namespace, аналогично классовые переменные - скрытые глобальные
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39787986
Foxpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arioch,

Класс имеет загруженный интерфейс, дёргая методы из которого можно управлять библиотекой. Приходится брать инициализированную переменную классом, и из переменной дёргать вызовы


Я подумал, что использовав анонимные переменные, я всегда буду иметь ссылку на класс из self процедуры, раз объявление
Код: pascal
1.
 Twrite =  function(const str: PAnsiChar; len: size_t): size_t of object cdecl; 



не работает
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788003
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну так этот интерфейс, он в момент времени один единственный, или их может быть одновременно много?

В случае первого - его можно положить в глобальную переменную, а чтобы "не засорять пространство" - функции и переменную спрятать в класс
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788035
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FoxpcArioch,

Класс имеет загруженный интерфейс, дёргая методы из которого можно управлять библиотекой. Приходится брать инициализированную переменную классом, и из переменной дёргать вызовы


Я подумал, что использовав анонимные переменные, я всегда буду иметь ссылку на класс из self процедуры, раз объявление
Код: pascal
1.
 Twrite =  function(const str: PAnsiChar; len: size_t): size_t of object cdecl; 



не работает
Вынесите методы которые являются параметрами чужого API в отдельный подкласс и просто используйте по назначению

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
TGodObject = class
private
  type
    TWinApi = class
    public
      class function Write(const str: PAnsiChar; len: size_t): size_t; cdecl; static; // class function и static обязательны
    end;
public
  // .... тут 100500 ваших методов
end;



Код: pascal
1.
ApiCall(TWinApi.Write); или ApiCall(@TWinApi.Write);

смотря как там описан вызов
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788108
Foxpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Блин. Нашёл вариант! В начале функции, мы присвоим self-у адрес на созданный класс

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
var
  Enigne: TEngine;

function TEngine.Write(const str: PAnsiChar; len: size_t): size_t;
begin
  Self := Enigne;

  BeginScene();
  Draw2DText(50,100, UTF8String(str), clred, 8);
  EndScene();
end;



Всё заполняется как надо. Но костыль не самый плохой
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788112
Фотография Dmitry Arefiev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FoxpcВсё заполняется как надо. Но костыль не самый плохой
Случай ...
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788113
Foxpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dmitry Arefiev,

я привык к тому, если под 64 битный компилятор тоже работает, и менеджер утечек молчит. Значит всё в порядке.

Вот так на много быстрее работает
Код: pascal
1.
  Move(Enigne, Self, SizeOf(TestEnigne));



А утечки памяти и не может быть. Потому что мы заимствуем память существующую. И когда мы уничтожим главный объект, все строки - листы, и прочее будет уничтожено в первом классе. А в скопированном будет лежать мусор, который уже не будет нужный
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788114
Foxpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Мне интересно, а можно вообще без копирования обойтись? Тоже так же как это делает TMethod при вызове.. Он же не создаёт класс заново?
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788124
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeyАнонимная функция это интерфейс с методом Invoke.Точнее экземпляр наследника TInterfacedObject с полями-параметрами
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788127
Foxpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ещё одно решение

Код: pascal
1.
2.
3.
  asm
    mov [self], offset Enigne
  end;



Но без ассемблера через код, никак такое не удалось сделать. Может кто подскажет как правильно написать ?Что бы он такое же с генерировал без писанины ассемблера
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788128
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
white_niggerТочнее экземпляр наследника TInterfacedObject с полями-параметрами
Нет.
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788132
Foxpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Kazantsev Alexey,

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
// Тут кидает в процедуру с первым jmp 
005D0D75 83442404F4       add dword ptr [esp+$04],-$0c
005D0D7A E911010000       jmp Enigne.CreateInit$ActRec.$0$Body 


005D0D7F 83442404F4       add dword ptr [esp+$04],-$0c
005D0D84 E9D7F0E3FF       jmp TInterfacedObject.QueryInterface
005D0D89 83442404F4       add dword ptr [esp+$04],-$0c
005D0D8E E9F5F0E3FF       jmp TInterfacedObject._AddRef
005D0D93 83442404F4       add dword ptr [esp+$04],-$0c
005D0D98 E907F1E3FF       jmp TInterfacedObject._Release
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788134
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Анонимки
program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils, System.Rtti;

type

TAnonFunc = reference to function(const a, b : string) : string;

TAnonFuncImpl = class(TInterfacedObject, TAnonFunc)

function Invoke(const a, b : string) : string;

end;

{ TAnonFuncImpl }

function TAnonFuncImpl.Invoke(const a, b : string) : string;
begin
result := '(' + a + b + ')';
end;

function GetAnonFunc(const APrefix : string) : TAnonFunc;
begin
result := function(const a, b : string) : string
begin
result := APrefix + a + b;
end;
end;

var

func : TAnonFunc;
intf : IInterface absolute func;
f : TRttiField;

begin

func := function(const a, b : string) : string // 1
begin
result := a + b;
end;

// func := GetAnonFunc('text - '); // 2

WriteLn(func('1', '2'));

for f in TRttiContext.Create.GetType(TObject(intf).ClassType).GetFields do
WriteLn(f.ToString);

func := TAnonFuncImpl.Create as TAnonFunc;

WriteLn(func('1', '2'));

ReadLn;

end.


1. Анонимки это интерфейсы.
2. Поля не для параметров, а для контекста (закомментировать 1, раскомментировать 2)
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788135
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
С форматированием
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, System.Rtti;

type

 TAnonFunc = reference to function(const a, b : string) : string;

 TAnonFuncImpl = class(TInterfacedObject, TAnonFunc)

  function Invoke(const a, b : string) : string;

 end;

{ TAnonFuncImpl }

function TAnonFuncImpl.Invoke(const a, b : string) : string;
begin
 result := '(' + a + b + ')';
end;

function GetAnonFunc(const APrefix : string) : TAnonFunc;
begin
 result := function(const a, b : string) : string
           begin
            result := APrefix + a + b;
           end;
end;

var

 func : TAnonFunc;
 intf : IInterface absolute func;
 f    : TRttiField;

begin

 func := function(const a, b : string) : string // 1
         begin
          result := a + b;
         end;

// func := GetAnonFunc('text - '); // 2

 WriteLn(func('1', '2'));

 for f in TRttiContext.Create.GetType(TObject(intf).ClassType).GetFields do
  WriteLn(f.ToString);

 func := TAnonFuncImpl.Create as TAnonFunc;

 WriteLn(func('1', '2'));

 ReadLn;

end.

...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788263
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FoxpcМне интересно, а можно вообще без копирования обойтись?

а это в зависимости от 21836382

AriochНу так этот интерфейс, он в момент времени один единственный, или их может быть одновременно много?

потому что

AriochВ случае первого - его можно положить в глобальную переменную, а чтобы "не засорять пространство" - функции и переменную спрятать в класс

а как сделать последнее тебе и написали

Ariochделай в классе статические КЛАССОВЫЕ методы, они по сути глобальные функции скрытые из глобального namespace, аналогично классовые переменные - скрытые глобальные

и даже показали


X-CiteВынесите методы которые являются параметрами чужого API в отдельный подкласс и просто используйте по назначению

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
TGodObject = class
private
  type
    TWinApi = class
    public
      class function Write(const str: PAnsiChar; len: size_t): size_t; cdecl; static; // class function и static обязательны
    end;
public
  // .... тут 100500 ваших методов
end;
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788266
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Foxpcмы присвоим self-у адрес на созданный класс

не на класс, а на объект

на класс никаких указателей не надо, он у тебя и так есть ,если функция не фиртуальная
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788270
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FoxpcЕщё одно решение

Код: pascal
1.
2.
3.
  asm
    mov [self], offset Enigne
  end;



Но без ассемблера через код, никак такое не удалось сделать. Может кто подскажет как правильно написать ?Что бы он такое же с генерировал без писанины ассемблера

Код: pascal
1.
2.
3.
4.
5.
6.
7.
procedure SetPtr(var Obj; Ptr: Pointer); inline;
begin
  Pointer(Obj) := Ptr;
end;

...
  SetPtr(Self, nil);
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788283
ziv-2014
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я использую вот эту CnCallBack.pas
StdcallMethodToCallBack(Self, @метод класса)
Ограничения:
1. только stdcall
2. реализована для x86. Для 64 битного режима не работает, там все сложнее. Хотя надо бы реализовать до кучи.
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788296
Foxpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kealon(Ruslan),

Я это пробовал, не работает. Он помещает указатель на self в edx а в eax адрес на pointer и потом делает mov [edx],eax и в итоге в регистре eax лежат левые данные
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788320
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Foxpc,

какая разница что в eax?
покажи код, тебе же надо в Self поместить адрес объекта

с этой трактовки offset Enigne выглядит довольно странно
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788340
Foxpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kealon(Ruslan),

Не странно, когда это класс.
...
Рейтинг: 0 / 0
Передача аннонимной функции в cи библиотеку
    #39788341
Foxpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
25 сообщений из 53, страница 1 из 3
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Передача аннонимной функции в cи библиотеку
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]