Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2009.11.08;
Скачать: [xml.tar.bz2];

Вниз

Классы в DLL на Delphi и MSVC++ (бой продолжается)...   Найти похожие ветки 

 
oxffff ©   (2008-09-15 23:39) [40]

Так, не поленился открыть VC.
ecx содержит указатель на экземпляр.
mov  dword ptr [ebp-8],ecx
То просто сохраняем в локальной переменной указатель на экземпляр.
То есть пароноидальное сохранение.

Отсюда вывод.

Автор у тебя соглашение не cdecl.

Вот твой вызов

lea         eax,[ebp+FFFFFF28h]  <- ccылка для результата
push       eax  
lea         ecx,[ebp-8]               <- указатель на экземпляр  
call        004111FE

Вот вызов для cdecl

virtual  SClassID __cdecl ClassID()

lea         eax,[ebp+FFFFFF28h]
push        eax  
lea         ecx,[ebp-8]
push        ecx  
call        00411203
add         esp,8


 
oxffff ©   (2008-09-15 23:45) [41]

У автора темы вызов __thiscall
The __thiscall calling convention is used on member functions and is the default calling convention used by C++ member functions that do not use variable arguments. Under __thiscall, the callee cleans the stack, which is impossible for vararg functions. Arguments are pushed on the stack from right to left, with the this pointer being passed via register ECX, and not on the stack, on the x86 architecture.


 
oxffff ©   (2008-09-16 00:06) [42]

Для автора.
Если тебе все же необходимо делать этот вызов __thiscall для delphi нужно немного сообразительности. Идея очень простая. Тебе нужно в delphi сделать фиктивный объект транслятор __thiscall в __stdcall в delphi.  

То есть создаешь некий объект вида

thisCallTostdcallWrapper=record
VMT:PVMT;
instance:DelphiInstance;
end;

VMT=array[1..MethodsCount] of pointer;
pVMT=^VMT;

где каждый указатель это указатель на код.

asm
push [esp];
mov ecx,[ecx+4];
mov [esp+4],ecx;
jmp stdcallMethodImpl;
end;

Процесс можно автоматизировать.
Это оставляем тебе в качестве домашнего задания. :)


 
oxffff ©   (2008-09-16 00:14) [43]


> Процесс можно автоматизировать.
> Это оставляем тебе в качестве домашнего задания. :)


Подсказка тебе просто необходимо генерировать код на лету.
Заменяя только смещение в jmp stdcallMethodImpl на лету.
То есть берешь Delphi объект и проходишь всю его VMT с генерацией кода.


 
Германн ©   (2008-09-16 00:28) [44]

<offtop>
Термин "плагин" в моих глазах упал ещё ниже. Плинтус уже где-то рядом. :)
</offtop>


 
Slym ©   (2008-09-16 10:13) [45]

oxffff ©   (16.09.08 0:14) [43]
Подсказка тебе просто необходимо генерировать код на лету.

проще сделать так

type
 TClassID=packed record
  a,b:LongWord;
 end;
 PClassDesc=^TClassDesc;
 TClassDesc=packed record
  IsPublic: function:LongBool;stdcall;
  Create: function(const Loading:LongBool):pointer;stdcall;
  ClassName:function :PChar;stdcall;
  SuperClassID:function:TClassID;stdcall;
  ClassID:function:TClassID;stdcall;
  Category:function :PChar;stdcall;
  FClassID:TClassID;
  OtherData:Pointer;

end;

function GetClassID:TClassID;stdcall;
var this:PClassDesc;
begin
 asm
   mov this, ecx
 end;

 result:=this^.FClassID;
end;

function LibClassDesc(const i:integer):TClassDesc;
begin
ZeroMemory(@result,SizeOf(result));
result.FClassID.a:=$FF00FF;
result.FClassID.b:=$AABBEE;

result.ClassID:=@GetClassID;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
ClassDesc:TClassDesc;
ClassID:TClassID;
begin
ClassDesc:=LibClassDesc(1);
asm
   lea ecx, ClassDesc
end;
ClassID:=ClassDesc.ClassID;
if (ClassID.a<>$FF00FF) or (ClassID.b<>$AABBEE) then raise exception.Create("Bad ClassID");
end;


 
oxffff ©   (2008-09-16 10:32) [46]


> Slym ©   (16.09.08 10:13) [45]


Ты кажется не в теме. Точнее не понял тему.

Код вызывается из С++ с __thiscall calling convention. А не из delphi

Во вторых твой код не корректный.

При stdcall функция очистит на стек на 4 больше, чем при __thiscall.

Ну и главное обращение по VMT косвенное, то если ты передаш в С++ код PClassDesc. То код свалиться, поскольку ждет вместо

IsPublic: function:LongBool;stdcall;

указатель на VMT.

P.S. Зачем писать код для каждой функции вручную, если можно его генерировать на ходу автоматически. Представь если у автора таких функций >10.



Далее


 
Slym ©   (2008-09-16 14:04) [47]

oxffff ©   (16.09.08 10:32) [46]
Код вызывается из С++ с __thiscall calling convention. А не из delphi

этим я эмулирую thiscall -
asm
  lea ecx, ClassDesc
end;
ClassID:=ClassDesc.ClassID;

oxffff ©   (16.09.08 10:32) [46]
При stdcall функция очистит на стек на 4 больше, чем при __thiscall

чистит ровно настолькоже т.к. это не метод класса и нет скрытого параметра self - чистит только 4 (указатель на результат)
oxffff ©   (16.09.08 10:32) [46]
Ну и главное обращение по VMT косвенное

не факт что VMT ждет, а скорее всего на структуру с фиксированными точками входа в процедуры, т.к. с++ ничего низнает о дельфевой VMT
oxffff ©   (16.09.08 10:32) [46]
Зачем писать код для каждой функции вручную, если можно его генерировать на ходу автоматически

Си позволяет инлайнить код объявленных методов в месте обявления, а дельфи при определении записи (record) нет... тат нужно типа хелперов как в старших дельфях, но в 7 их нету


 
oxffff ©   (2008-09-16 15:09) [48]


> Slym ©   (16.09.08 14:04) [47]


Ты должен передать С++ коду указатель на экземпляр  класса, с коим код С++ будет взаимодейстовать вызывая его виртуальные методы через VMT с __thiscall.
Механизм вызова у них идентичен, за исключение того что в С++ VMT плавающий.
Здесь нет речи про Inline. Здесь косвенный вызов, нет прямой линковки.

function GetClassID:TClassID;stdcall;
var this:PClassDesc;
begin
asm
  mov this, ecx
end;
result:=this^.FClassID;
end;

Теперь я понял, что это у тебя обычный метод. Однако в твоем случае нет гарантии того, что в ecx то, что должно быть.
+ нужно писать код вручную.
Я предлагаю этот процесс автоматизировать. То есть автор пишет методы в delphi  c stdcall, а обертка транслирует вызовы __thiscall в stdcall.


 
oxffff ©   (2008-09-16 15:55) [49]

Например вот функция ты передаешь ей sdtcall функцию,  оно возвращает обертку для преобразования из __thiscall вызова.
Пользуясь ею генерируешь свою таблицу VMT у объекта обертки реального объекта. Особо не тестил, так что прошу сильно не бить.

function Generate__ThisCallStub(StdCallee:pointer):pointer;
Label StubStartLabel,StubEndLabel;
var  StubStart:pointer;
    StubSize:DWORD;
    fixOffset:DWORD;
    OffsetValue:DWORD;
begin
try
result:=nil;
 asm
 mov StubStart,offset StubStartLabel;
 mov StubSize,offset StubEndLabel;
 sub StubSize,offset StubStartLabel;
 mov fixOffset,Offset StubEndLabel;
 sub fixOffset,offset StubStartLabel;
 end;
GetMem(result,StubSize);
try
CopyMemory(result,StubStart,StubSize);
OffsetValue:=DWORD(StdCallee)-DWORD(result)-fixOffset;
asm
mov eax,fixOffset
lea eax,[eax-4];
add eax,result;
mov edx,OffsetValue;
mov [eax],edx;
end;
except
FreeMem(result);
raise;
end;
except
end;
exit;
///////////////////////////////////////////////////////////////////////////////
//Generic code
///////////////////////////////////////////////////////////////////////////////
asm
StubStartLabel:
push [esp];
mov ecx,[ecx+4];
mov [esp+4],ecx;
DB $E9;
DD $0;
StubEndLabel:
end;
end


 
ПЗ   (2008-09-16 20:53) [50]

У меня три вопроса:
1. Вчера выкладывал шот той же функции ClassID() на VС без дебаг-опций:

mov ecx, dword ptr [sid]
mov [eax], dword ptr [esp+4]
mov dword ptr [eax], ecx
mov edx, dword ptr [sid+4]
mov dword ptr [eax+4],edx
ret 4

Здесь нет этих наворотов с  
push       eax  
lea         ecx,[ebp-8]
Это нормально?

2. А нельзя внутри этого же метода на делфи тупо увеличить add esp,4 ? this все равно внутри не используется.

3. У меня ведь куча методов в этом классе. Как определить, какие из них thiscall, а какие – cdecl ? Вот, например, перед ClassID() вызывается аналогичный SuperClassID(), который возвращает число. Он работает одинаково хорошо что на С что на Делфи и стек никуда не смещается. Есть некоторые другие методы, к которым у меня нет вопросов. Неужели методом тыка трассировать все?


 
ПЗ   (2008-09-16 21:29) [51]

Oh yeah!

Дамы и господа, одержана первая победа над гегемонией С++!
хттп://i032.radikal.ru/0809/cc/e077a7bb68f5.jpg

Ларчик открылся просто:
function ClassDesc.ClassID():MClass_ID;cdecl;
begin
 Result:=m_id;
 asm
   pop ebp
   ret 4
 end;

end;
Пока я не уверен, что это корректный способ, но он сработал. 3ds загрузилась и увидела делфёвый плагин. Бой выигран, но впереди еще тяжелое сражение за функциональность данного плагина. Надеюсь на дальнейшее плодотворное сотрудничество. Всех мастеров благодарю за консультации!


 
oxffff ©   (2008-09-16 23:24) [52]


> Дамы и господа, одержана первая победа над гегемонией С++!


К сожалению нет. Так ты себе еще больше проблем создашь!!!
Рекомендую досконально разобраться в форме вызова на стороне С++, и сделать соответствие на delphi.


 
Германн ©   (2008-09-17 02:05) [53]

Долго пытался удержаться, но не могу более.
Увидел asm инструкцию RET внутри Паскалевской процедуры...
Нет слов.


 
Slym ©   (2008-09-17 05:03) [54]

ПЗ   (16.09.08 21:29) [51]
pop ebp

огребеш...
вольному/бездумному изменению регистров используй eax,edx,ecx; остальное для отпиливание ножек у табуретки с петлей на шее


 
ПЗ   (2008-09-17 21:04) [55]

Если уж разбираться досконально, то надо иметь ответы на вышепоставленные вопросы. Почему именно этот злополучный метод стал thiscall? В реальности, кстати, он не структуру, а класс должен возвращать (по-значению, т.е., через стек).
Я добавил
pop ebp
ret 4

не от балды, а так, как это получается на С.
Теперь ClassID() имеет вид:

push ebp
mov  ebp,esp
mov eax,[ebp+$08]
mov edx,[m_id]
mov [eax],edx
mov edx,[m_id+$4]
mov [eax+$04],edx

pop ebp <=мой код
ret ;004 <=мой код

pop ebp
ret

Кримина лишь в том, что я не могу досконально разобраться, почему так, а не иначе. Насчет второго ret, спорно – ведь мы не боимся делать в функциях if ... then Exit(code). Зато теперь стек у меня пришел в то состояние, в котором должен быть (я сличал) . Работы еще много, пойду пока дальше, там посмотрим как будет работать. В случае сбоев буду кумекать с переадресацией вызова. Из-за одного метода переделывать все мне что-то не хочется.


 
oxffff ©   (2008-09-17 23:23) [56]


> Если уж разбираться досконально, то надо иметь ответы на
> вышепоставленные вопросы. Почему именно этот злополучный
> метод стал thiscall? В реальности, кстати, он не структуру,
>  а класс должен возвращать (по-значению, т.е., через стек).
>


Покажи передачу параметров в С++ примере на ASM.


> if ... then Exit(code).


Есть моменты которые делает Delphi за тебя, а именно корректно разматывает SEH фреймы(конструкции try\except\finally),а также финализирует переменные.


 
Slym ©   (2008-09-18 08:37) [57]

oxffff ©   (17.09.08 23:23) [56]
а также финализирует переменные

+1
с ручным ret динамические структуры типа строк и дин массивов не сфинализируются, что приведет к утечке памяти


 
ПЗ   (2008-09-18 20:52) [58]

>Покажи передачу параметров в С++ примере на ASM.
----------------------------------------
Каких параметров? Возвращаемый результат идет через стек:

После возврата из ClassID()
0x0012DD38  ff 00 ff 00  &#255;.&#255;. <= ESP
0x0012DD3C  ee bb aa 00  &#238;»&#170;.
0x0012DD40  00 00 00 00  ....
0x0012DD44  48 90 2e 0d  H&#144;..
0x0012DD48  80 12 0c 66  &#128;..f
0x0012DD4C  c0 80 cb 08  &#192;&#128;&#203;.
0x0012DD50  d0 e2 12 00  &#208;&#226;..
0x0012DD54  17 92 7b 65  .&#146;{e

Остальное видно на снимках с отладчика, которые я выше приводил.

>Есть моменты которые делает Delphi за тебя, а именно корректно разматывает SEH фреймы(конструкции try\except\finally),а также финализирует переменные.
---------------------------------------
Я исключения в DLL не использую, если только внутренняя реализация Делфи. Но тут вопрос: а что я нарушил вместо RET сделав RET 4 ? Состояние стека у меня как раз пришло в норму. Это я не оправдываюсь, а сам пытаюсь понять, чего накуролесил :-)

> с ручным ret динамические структуры типа строк и дин массивов не сфинализируются, что приведет к утечке памяти
--------------------------------------
Динамические массивы я не использую, классы убивает сам MAX, а ANSI-строки… Хм. Память выделяется, память очищается. Надо понаблюдать, но думаю, в таких монстрах как МАХ утечек вряд ли удается избежать. Как RET 4 мог повилять?


 
Сергей М. ©   (2008-09-18 21:16) [59]


> он не структуру, а класс должен возвращать


Дельфийский что ли класс ?
Ну ты и кулибин, однако)


 
ПЗ   (2008-09-19 22:33) [60]

>Дельфийский что ли класс ?
>Ну ты и кулибин, однако)
------------------------------------------------
Что значит дейльфийский и почему кулибин - я? Autodesk хочет, чтобы плагины были на С, а я хочу на Делфи :-) Соответственно, Autodesk дает заголовочники С, в которых определен класс Class_ID – та же структура с полями a,b плюс несколько методов для доступа к ним. Методы не виртуальные (!) и в реальности она их не вызывает (проверил). Передача через стек по-значению, на выходе в стеке лежит тот же результат, что и со структурой (тоже проверил). Record нормально заглатывается что на С, что на Делфи.


 
GrayFace ©   (2008-09-21 02:05) [61]

ПЗ   (17.09.08 21:04) [55]
Почему именно этот злополучный метод стал thiscall?

Потому что все методы классов - thiscall по умолчанию.
Надо просто делать функции stdcall и создавать из них массив. Примерно так:

MClass_ID = packed record
a,b:LongWord;
end;

procedure ClassID():MClass_ID;
begin
  Result:=m_id;
end;

var MyVMT: packed array[0..0] of Pointer =
(
@ClassID // здесь через запятую все виртуальные методы.
);

const MyObject: Pointer = @MyVMT[0];

И подавай ему MyObject в качестве объекта.


 
GrayFace ©   (2008-09-21 02:06) [62]

*И подавай ему @MyObject в качестве объекта.


 
Slym ©   (2008-09-21 17:15) [63]

GrayFace ©   (21.09.08 2:05) [61]
и получится менее наглядная реализация Slym[26]


 
ПЗ   (2008-09-22 20:52) [64]

>Потому что все методы классов - thiscall по умолчанию.
Идея понятна, если нынешняя реализация сбойнет, пойду этим путем.
Но почему нестыковки по стеку у меня вышли только с одним методом (а там их туева хуча)? Остальные работают идентично как в С, так и в Делфи. Они у меня помечены cdecl. И только ClassID() сбойнул. Например –
function ClassDesc.SuperClassID():SClass_ID;cdecl;
begin
 Result:=UTILITY_CLASS_ID;
end;

Сча я пошел дальше. Среди прочих есть
function ClassDesc.MyUtilCreate(loading:Boolean=FALSE):Pointer;cdecl;   // return a pointer to an instance of the class.
begin
 myUtil:=TUtility.Create;
 Result:=myUtil;
end;

Он возвращает в 3ds экземпляр TUtility, из которого 3ds вызывает уже другие методы (тоже мои, на Делфи) . Пока всё ОК. Теперь мне в одном из методов TUtility, приняв указатель от 3ds надо вызвать метод его, 3ds, внутреннего объекта. То есть, обратная задача. Сча над ней работаю.


 
GrayFace ©   (2008-09-24 02:56) [65]

Slym ©   (21.09.08 17:15) [63]
и получится менее наглядная реализация Slym[26]

Зато меньше писать :)

ПЗ   (22.09.08 20:52) [64]
function ClassDesc.SuperClassID():SClass_ID;cdecl;

Дак она же без параметров.

ПЗ   (22.09.08 20:52) [64]
Теперь мне в одном из методов TUtility, приняв указатель от 3ds надо вызвать метод его, 3ds, внутреннего объекта.

объявляй так:
TSome3DSMethod = function(p1, p2:int; this:Pointer; Параметры в обратном порядке):тип_возвращаемого_значения register;
в качестве p1, p2 подавай любые числа, например, нули.


 
ПЗ   (2008-09-24 22:12) [66]


> Дак она же без параметров.

Дак и Class_ID был без параметров:
ClassDesc=class
...
function SuperClassID():SClass_ID;virtual;cdecl;
function ClassID():MClass_ID;virtual;cdecl;
...
end;
Ы?


> TSome3DSMethod = function(p1, p2:int; this:Pointer; Параметры
> в обратном порядке):тип_возвращаемого_значения register;
>

Настоящие герои всегда идут в обход? :-)
Для начала я попробую объявить его как положено:
Max_Interface=class
...
   function AddRollupPage(hInst:HINSTANCE; dlgTemplate:PChar; dlgProc:DLGPROC; title:PChar; param:LPARAM=0; flags:DWORD=0; category:Integer= ROLLUP_CAT_STANDARD ):HWND;virtual; cdecl; abstract;
...
end;
Я как раз закончил PHP-скрипт, который перевел мне заголовочник SDK с С++ *.H в *.PAS. Осталось ручками порядок навести и можно будет проверить.

Вопрос: как в VMT отражаются overload-методы?
function F(a:Integer):Boolean;
function F(a:Word):Boolean;

Это будет одна запись или две подряд?


 
GrayFace ©   (2008-09-25 00:57) [67]

Блин, до меня только сейчас дошло про ret 4. Пиши везде stdcall и не мучайся. :) Никаких наворотов не надо.

ПЗ   (24.09.08 22:12) [66]
Это будет одна запись или две подряд?

Не знаю, позволит ли он конкретно это, но overload-методы - это, конечно, разные записи. Наверняка подряд, но я не проверял.


 
ПЗ   (2008-09-25 20:45) [68]


> >Пиши везде stdcall и не мучайся. :) Никаких наворотов не
> надо.


Уже писал. Не работает. Стек сдвигается.
Нормально работает только cdecl. Кроме ClassID, в который кроме cdecl пришлось воткнуть ret 4. Вот такая загогулина.


 
GrayFace ©   (2008-09-27 20:01) [69]

А, нет, туплю - там же взвращается структура, соответственно, передается на нее указатель, так что это __thiscall.


 
ПЗ   (2008-09-27 21:07) [70]

Но ответа на вопрос №55 я так и не нашел :-(

> Почему именно этот злополучный метод стал thiscall?


 
GrayFace ©   (2008-09-28 10:50) [71]

Они все должны быть thiscall. Среди других есть методы с параметрами или возвращающие структуру? Видимо нет, или в их случае сдвиг esp не приводит к проблемам. Можешь проверить - если self они определяют неправильно, то thiscall.


 
ПЗ   (2008-09-28 20:02) [72]

Из тех методов, которые 3ds реально вызывает на моей практике с параметром например
function Creat(loading:Boolean=FALSE):Pointer;virtual;cdecl;
А как проверить, правильно ли они определяют self?

Попутно возник еще вопрос. Многие методы Autodesk в своих заголовчниках определяет как
CoreExport void SetClassDesc(ClassDesc* i_cd);
где
#ifdef BLD_CORE
#define CoreExport __declspec( dllexport )
#else
#define CoreExport __declspec( dllimport )
#endif

То есть, метод либо экспортируется, либо импортируется из DLL. ВОПРОС: CoreExport в этом случае помещает метод в VMT ?


 
Slym ©   (2008-09-29 04:18) [73]

ПЗ   (28.09.08 20:02) [72]
А как проверить, правильно ли они определяют self?

например так :)
function Creat(loading:Boolean=FALSE):Pointer;virtual;cdecl;
begin
 result:=self.Creat(loading);
end;

если СтекОверфлоу значед self рабочий если АцесВиолейшн значед нерабочий :)


 
GrayFace ©   (2008-09-29 20:37) [74]

ПЗ   (28.09.08 20:02) [72]
То есть, метод либо экспортируется, либо импортируется из DLL. ВОПРОС: CoreExport в этом случае помещает метод в VMT ?

нет, он же не virtual.


 
ПЗ   (2008-09-29 21:36) [75]

А как он тогда экспортируется?

Возвращаясь к thiscall и ret 4. В MSDN написано: [i] This is the default calling convention used by C++ member functions that do not use variable arguments. Under thiscall, the callee cleans the stack, which is impossible for vararg functions. [/i] где под vararg понимается [i] Indicates a variable number of arguments. [/i]  то есть, thiscall – стандартное соглашение о вызовах для всех методов, кроме тех, что используют переменное число параметров. У меня нет ни одного такого метода. То есть, [b]ВСЕ[/b] методы должны быть thiscall? Сегодня проверил, self внутри них не определен. Вопрос: КТО должен класть THIS в регистр ECX? Если верить отладчику, вызывающая программа у меня этого не делает. Может неявно?

Внутри методов мне self не нужен и на ECX мне тож начхать. Ничем другим thiscall от stdcall не отличается. Но stdcall после возврата сдвигает мне стек на ячейку. Как выкрутиться?

Вот еще пример:
procedure TUtility.BeginEditParams(ip:TInterface; iu:IUtil);cdecl;
begin
 self.ip:=ip;
end;
При вызове 3ds передает ему через регистр указатель на объект ip, а iu не передает вообще. Проверил на сях, все работает. Дизассемблировал на делфях. Вызывающая сторона (3ds):

mov edx,[edi] <– адрес метода BeginEditParams
push eax <– eax=$035BD508 – адрес объекта ip
call edx
....  <- код, не связанный с очисткой стека

Тело метода BeginEditParams:

push ebp
mov ebp,esp
mov eax,[ebp+$0c] <- self.ip:=ip;
mov edx,[ebp+$08]
mov[edx+$08],eax
pop ebp
ret

Как нетрудно видеть, в стеке по адресу [ebp+$0c]  параметр ip лежать никак не может. Что не так?


 
Slym ©   (2008-09-30 04:10) [76]

ПЗ   (29.09.08 21:36) [75]
а iu не передает вообще

procedure TUtility.BeginEditParams(ip:TInterface; iu:IUtil);cdecl;
begin
self.ip:=ip;
end;
да потомучто self потомучно procedure of object;
потомучто дельфи ждет не 2 параметра как ты хочешь, а ТРИ
procedure BeginEditParams(self:TUtility;ip:TInterface; iu:IUtil);cdecl;


 
Slym ©   (2008-09-30 04:12) [77]

procedure TUtility.BeginEditParams(param2:pionter);cdecl;
var ip:TInterface; iu:IUtil;
begin
 ip:=TInterface({param1}self);
 iu:=IUtil(param2);
end;


 
GrayFace ©   (2008-10-01 10:08) [78]

ПЗ   (29.09.08 21:36) [75]
Вопрос: КТО должен класть THIS в регистр ECX? Если верить отладчику, вызывающая программа у меня этого не делает.

должна она.

ПЗ   (29.09.08 21:36) [75]
Как выкрутиться?

Как в [61] или [26]


 
Dimka Maslov ©   (2008-10-01 13:38) [79]

В данном случае проще написать библиотеку-оболочку на С++, которая в свою очередь будет уже вызывать дельфийскую


 
ПЗ   (2008-10-01 22:28) [80]

Проще. Но я преследую чисто исследовательские цели. Буду продираться.

Вот например, если вышеупомянутый ClassID сделать stdcall то при возврате структуры m_id по-значению (a,b:Integer) компилятор вставляет в конце ret 8. То есть, он хочет освободить 8 байт стека, якобы выделенных под результат? Однако на сях thiscall в этом же случае ставит ret 4, хотя в стек кладет тот же 8-байтовый результат. Нельзя ли их как-нибудь помирить малой кровью?



Страницы: 1 2 3 вся ветка

Форум: "Основная";
Текущий архив: 2009.11.08;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.65 MB
Время: 0.009 c
15-1252510755
TUser
2009-09-09 19:39
2009.11.08
Опрос (ну или явка с повинной :))


2-1252574162
vegarulez
2009-09-10 13:16
2009.11.08
Вопрос про Edit1.OnKeyPress (D7)


1-1223364687
Vlad Oshin
2008-10-07 11:31
2009.11.08
DLL, с пакетами, использую DevExpress, компоненты xxDockxx, AV


1-1222628088
Castello
2008-09-28 22:54
2009.11.08
Общение между приложениями


2-1253263783
Прима
2009-09-18 12:49
2009.11.08
array [0..0] of ...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский