Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.139.72.78] |
|
Сообщ.
#1
,
|
|
|
Доброй ночи!
Есть код на C++, запускается. Нужно то же только на Delphi, вроде все один в один но access violation. Что я делаю не так с вызовом абстрактных классов и как нужно? typedef char* (*CrIntFunc) (const char *Name); class CSomeClass { public: virtual void Dummy1(void) = 0; virtual void Method1(void) = 0; virtual void Method2(void) = 0; virtual int Method3(const char *param1, const char *param2 = NULL) = 0; }; void main() { HMODULE hDLL = LoadLibrary("MYDLL.dll"); if(!hDLL) { MessageBox(NULL, "hDLL=0", "ERROR", MB_OK); return 1; } CrIntFunc Func = (CrIntFunc)GetProcAddress(hDLL,"CreateInterface"); CSomeClass* pSomeClass = (CSomeClass*)Func("String_ident"); pSomeClass->Method1(); } type TCrIntFunc = function(cszname: pChar): Pointer; cdecl; TSomeClass = class procedure Dummy1; virtual; abstract; procedure Method1; virtual; abstract; procedure Method2; virtual; abstract; function Method3(param1, param2: PChar):integer; virtual; abstract; end; begin hDLL := LoadLibrary('MYDLL.dll'); CrIntFunc := GetProcAddress(hDLL, 'CreateInterface'); addr := CrIntFunc('String_ident'); SomeClass := TSomeClass(addr); SomeClass.Method1; //тут вылетает end. Дебаг вывожу в консоль - и hDLL, и addr имеют правильные значения, не nil. |
Сообщ.
#2
,
|
|
|
Delphi какая версия - юникодная?
Это что - получение интерфейса? |
Сообщ.
#3
,
|
|
|
По сути да, в DLL (C++) описан интерфейс со всеми методами, экспортируется единственная функция CreateInterface.
В представленном коде на С++ ошибок не возникает. Delphi 7, но тут ничего на языках отличных от английского не будет потому не принципиально. Я не думаю что CreateInterface нужно вызывать с параметром типа PWideChar, DLL писалась 10 лет назад. hDLL имеет значение 10000000 Ошибка Access violation at address 100052C8 in module 'MYDLL.dll' - судя по адресу ошибка возникает в DLL, но судя по тому что из C++ кода все работает - это результат моих кривых рук либо какой-то несовместимости Delphi и C++. В одной статье видел подсказку по поводу stdcall но тут метод без параметров, и результат с ним такой же, вплоть до тех же адресов. |
Сообщ.
#4
,
|
|
|
работать не будет по многим причинам.
* реализация классов и vtable у паскаля и с++ разная * ты не говоришь на каком языке написана MYDLL.dll. пс. подозреваю то из за чего работает первый вариант, так это то что библиотека написана на этих самых плюсах что бы код работал кросс-языково нужно уйти от vtable или заменить класс интерфейсом. * ты можешь заменить класс структурой с методами typedef void (*TMyMethod1) (); typedef int (*TMyMethod3) (const char *param1, const char *param2); struct CSomeClass { TMyMethod1 Dummy1; TMyMethod1 Method1; TMyMethod1 Method2; TMyMethod3Method3; }; это ровно также будет работать и в делфи * ты можешь перейти на интерфейсы. тогда не надо будет парится по поводу self это не значит что нужно работать через com, просто объявить, реализовать и возвращать его через библиотеку. тогда паскаль при вызове интерфейса не будет опираться на свой vtable, а не посредственно вызывать методы интерфейса Добавлено пс. я понимаю что структура и класс для c++ одно и тоже (почти), но отсутствие виртуальных методов как раз не будет создавать vtable |
Сообщ.
#5
,
|
|
|
Цитата ViktorXP @ * реализация классов и vtable у паскаля и с++ разная А в чем же различие (применительно к текущему случаю)? AFAIK и там и там - одно и тоже. объект указывает на VMT, VMT - указывает на массив указателей методов. Первый (нулевой) указатель - это и есть указатель на метод Dummy. В дельфи все вирт методы TObject - имеют отрицательное смещение, поэтому ни на что не влияют Цитата Виталь @ В одной статье видел подсказку по поводу stdcall но тут метод без параметров, и результат с ним такой же, вплоть до тех же адресов. у любого экземплярного метода есть скрытый параметр Self (this в плюсах). У тебя в классах не факт что stdcall используется. Попробуй cdecl или thiscall |
Сообщ.
#6
,
|
|
|
Добрый вечер. Спасибо за интерес к теме. Да, библиотека на плюсах.
Цитата что бы код работал кросс-языково нужно уйти от vtable или заменить класс интерфейсом Это нужно сделать в вызывающей программе на Delphi или в вызываемой библиотеке тоже? Исходников библиотеки нет и не будет, потому если менять надо оба то это сразу не вариант. Еще вопрос по теме. Если в самой библиотеке объявлен не класс, а именно интерфейс, и это я по незнанию описал его как класс, при этом в коде на С++ такая штука заработала - может быть такое или нет? На самом деле библиотека очень слабо описана, работаешь почти вслепую. Цитата Попробуй cdecl или thiscall Попробовал явно указать cdecl и stdcall procedure Method1; virtual; cdecl; abstract; ошибка вылазит абсолютно одинаковая, а thiscall в Delphi пишут что нет. Цитата Access violation at address *** in module 'MYDLL.dll'. Write of address ***. |
Сообщ.
#7
,
|
|
|
Виталь, А чем скомпилирована библиотека?
В Delphi действительно нету thiscall, а именно он и используется в данном случае. Точнее его вариация, зависит от компилятора (gcc, microsoft vs). Если нету исходников, либо других АПИ, то варианта два: Простой вариант - можно сделать на С++ библиотеку "враппер", которая будет вызывать нужные классовые функции и иметь простые функции для экспорта. И не простой вариант, дергать функции напрямую, при этом изображая thiscall. Довольно муторно, но реально |