У меня есть несколько скомпилированных библиотек DLL MSVC++, для которых я создал COM-подобные (облегченные) интерфейсы (абстрактные классы Delphi). Некоторые из этих классов имеют методы, которым нужны указатели на объекты. Эти методы C++ объявлены с использованием соглашения о вызовах __thiscall (которое я не могу изменить), которое аналогично __stdcall, за исключением того, что передается указатель this. в реестре ЕСХ.
Я создаю экземпляр класса в Delphi, а затем передаю его методу C++. Я могу установить точки останова в Delphi и увидеть, как он сработает с открытыми методами __stdcall в моем классе Delphi, но вскоре я получаю STATUS_STACK_BUFFER_OVERRUN, и приложение должно закрыться. Можно ли эмулировать/иметь дело с __thiscall на стороне Delphi? Если я передаю объект, созданный системой C++, тогда все хорошо, и методы этого объекта вызываются (как и следовало ожидать), но это бесполезно - мне нужно передать объекты Delphi.
Edit 2010-04-19 18:12 Вот что происходит более подробно: первый вызванный метод (setLabel) завершается без ошибок (хотя это метод-заглушка). Второй вызываемый метод (init) запускается, а затем умирает при попытке прочитать параметр vol.
Сторона C++
#define SHAPES_EXPORT __declspec(dllexport) // just to show the value
class SHAPES_EXPORT CBox
{
public:
virtual ~CBox() {}
virtual void init(double volume) = 0;
virtual void grow(double amount) = 0;
virtual void shrink(double amount) = 0;
virtual void setID(int ID = 0) = 0;
virtual void setLabel(const char* text) = 0;
};
Сторона Делфи
IBox = class
public
procedure destroyBox; virtual; stdcall; abstract;
procedure init(vol: Double); virtual; stdcall; abstract;
procedure grow(amount: Double); virtual; stdcall; abstract;
procedure shrink(amount: Double); virtual; stdcall; abstract;
procedure setID(val: Integer); virtual; stdcall; abstract;
procedure setLabel(text: PChar); virtual; stdcall; abstract;
end;
TMyBox = class(IBox)
protected
FVolume: Double;
FID: Integer;
FLabel: String; //
public
constructor Create;
destructor Destroy; override;
// BEGIN Virtual Method implementation
procedure destroyBox; override; stdcall; // empty - Dont need/want C++ to manage my Delphi objects, just call their methods
procedure init(vol: Double); override; stdcall; // FVolume := vol;
procedure grow(amount: Double); override; stdcall; // Inc(FVolume, amount);
procedure shrink(amount: Double); override; stdcall; // Dec(FVolume, amount);
procedure setID(val: Integer); override; stdcall; // FID := val;
procedure setLabel(text: PChar); override; stdcall; // Stub method; empty.
// END Virtual Method implementation
property Volume: Double read FVolume;
property ID: Integer read FID;
property Label: String read FLabel;
end;
Я бы наполовину ожидал, что использование одного stdcall сработает, но что-то не так, не знаю, что, возможно, что-то делать с используемым регистром ECX? Помощь будет принята с благодарностью.
Edit 2010-04-19 17:42 Может ли быть так, что регистр ECX необходимо сохранять при входе и восстанавливать после выхода из функции? Требуется ли указатель this для C++? Я, вероятно, просто достиг в данный момент, основываясь на некоторых интенсивных поисковых запросах Google. Я нашел что-то связанное, но, похоже, дело в обратном этого вопроса.
N
аргументов, включаяthis
. Получатель удаляет толькоN-1
аргументов, потому что считает, чтоthis
находится в регистре ECX, а не в стеке. В конечном итоге это обязательно приведет к переполнению стека. - person Rob Kennedy   schedule 19.04.2010this
в ECX, но ваш код Delphi ожидает, что он будет в первом параметре стека. Все остальные параметры стека также отключены на единицу. У меня есть техника, которая может решить эту проблему. Единственное, что меня беспокоит при использовании его с этим кодом, — это деструктор класса. Сегодня постараюсь написать описание. Он будет основан на моей работе над API расширенного редактирования без окон: pages.cs .wisc.edu/~rkennedy/windowless-rtf - person Rob Kennedy   schedule 19.04.2010