Импорт функций из делфёвой DLL
От: Walth Украина  
Дата: 26.06.07 15:10
Оценка:
Всем доброго времени суток!

Кто нибудь подскажет как правильно импортировать функцию

function clErrorMsg(ErrNo: integer): shortstring; stdcall;

в VC++

я делаю так

typedef char* (CALLBACK *PFN_clErrorMsg)(int ErrNo);
PFN_clErrorMsg pfnclErrorMsg;

Что неправильно? Как я подозреваю что-то не так с возвращаемым значением.
Только ума не приложу как shortstring принять в C.

Если кто-то подскажет где можно почитать о приведении типов Делфи и C++ или
точнее об импортировании из делфёвых DLL функций в C++ буду очень благодарен
и даже счастлив.



27.06.07 13:22: Перенесено модератором из 'C/C++' — Хитрик Денис
Re: Импорт функций из делфёвой DLL
От: Centaur Россия  
Дата: 26.06.07 18:35
Оценка:
Здравствуйте, Walth, Вы писали:

W>Всем доброго времени суток!


W>Кто нибудь подскажет как правильно импортировать функцию


W>function clErrorMsg(ErrNo: integer): shortstring; stdcall;


W>в VC++



W> я делаю так


W> typedef char* (CALLBACK *PFN_clErrorMsg)(int ErrNo);

W> PFN_clErrorMsg pfnclErrorMsg;

W> Что неправильно? Как я подозреваю что-то не так с возвращаемым значением.

W> Только ума не приложу как shortstring принять в C.

Всё неправильно. Тип shortstring не предназначен для работы через границу DLL. Собственно, он и в Delphi-то остался только для совместимости со старым Turbo Pascal’евским кодом.

Функция, экспортируемая из DLL и возвращающая в результате строку, должна принимать на вход указатель на буфер и размер его. Как-нибудь так:

procedure clErrorMsg(ErrNo: INT; buf: PCHAR; bufSize: DWORD); stdcall; export;

typedef void (__stdcall *pfErrorMsg)(INT errNo, PCHAR buf, DWORD bufSize);




Далее следует немного ссылок, пользуясь которыми, можно сделать изврат, который будет работать на одной конкретной версии компилятора Delphi.

Delphi 7 Help, ключевые слова "functions, returning results":

For a string, dynamic array, method pointer, or variant result, the effects are the same as if the function result were declared as an additional var parameter following the declared parameters. In other words, the caller passes an additional 32-bit pointer that points to a variable in which to return the function result.


Delphi 7 Help, ключевые слова "short strings:ShortString":

A ShortString is 0 to 255 characters long. While the length of a ShortString can change dynamically, its memory is a statically allocated 256 bytes; the first byte stores the length of the string, and the remaining 255 bytes are available for characters.

Re[2]: Импорт функций из делфёвой DLL
От: Walth Украина  
Дата: 26.06.07 19:19
Оценка:
Здравствуйте, Centaur, Вы писали:

Очень благодарен за ответ.

Я конечно виноват, что сразу не сказал, у меня есть DLL сделанный на Делфи, но у меня нет его исходников. Есть также интерфейсный файл для этой DLL тоже написанный на Делфи.

C>Тип shortstring не предназначен для работы через границу DLL.

Этого не знал.
Не значит ли это, что к такой функции
function  clErrorMsg(ErrNo: integer): shortstring; stdcall;

я не достучусь из VC++? Т.е. Другими словами я попал?

C>Функция, экспортируемая из DLL и возвращающая в результате строку, должна принимать на вход указатель на буфер и размер его.

Если бы так было — возможно я бы и не написал сюда.

Всё равно большое спасибо Вам зо ответ.
Re[3]: Импорт функций из делфёвой DLL
От: Centaur Россия  
Дата: 26.06.07 21:53
Оценка:
Здравствуйте, Walth, Вы писали:

W>Я конечно виноват, что сразу не сказал, у меня есть DLL сделанный на Делфи, но у меня нет его исходников. Есть также интерфейсный файл для этой DLL тоже написанный на Делфи.


Берётся Delphi той же версии, которой скомпилирована DLL. Пишется DLL-обёртка с правильным C-интерфейсом. Опционально над этой обёрточной DLL пишется ещё C++-обёртка, возвращающая std::string.

Либо делается извратный изврат, основанный на знании внутреннего строения ShortString и того, как он возвращается из Delphi-функций. Например, такой:

#pragma pack(push)
#pragma pack(1)
class ShortString
{
private:
  unsigned char length;
  char characters[256]; // 255 + terminating zero
public:
  const char* c_str() const { characters[length] = 0; return &characters[0]; }
  size_t size() const { return length; }
  char& operator[](size_t i) { return characters[i]; }
  char operator[](size_t i) const { return characters[i]; }
  // вложенные типы и функции контейнеров — begin, end и т. д. по вкусу
};
#pragma pack(pop)

typedef void (__stdcall *pfErrorMsg)(int ErrNo, ShortString* Result);

[…]

void use(const char*);

pfErrorMsg clErrorMsg = …;
ShortString ss;
(*clErrorMsg)(42, &ss);
use(ss.c_str());
Re: Импорт функций из делфёвой DLL
От: Аноним  
Дата: 27.06.07 10:41
Оценка:
Если не ошибаюсь ShortString это массив из 128 чаров. Возможно с длиной вначале. Т.е. стоит попробовать принять такие вещи:

typedef char DelphiShortString[128];

typedef struct
{
int len;
char DelphiShortString[128];
}DelphiShortString;

typedef struct
{
unsigned char len;
char DelphiShortString[128];
}DelphiShortString;

typedef struct
{
char DelphiShortString[128];
int len;
}DelphiShortString;

typedef struct
{
char DelphiShortString[128];
unsigned char len;
}DelphiShortString;

Авось какое сработает.
Re[2]: Импорт функций из делфёвой DLL
От: OdesitVadim Украина  
Дата: 27.06.07 10:52
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Если не ошибаюсь ShortString это массив из 128 чаров. Возможно с длиной вначале.

Если точнее, то это массив на 256 байт. Первый байт это длина строки. остальные 255 — собственно сама строка. Нуля в конце строки нет, как принято в С.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Импорт функций из делфёвой DLL
От: Аноним  
Дата: 27.06.07 10:53
Оценка:
А>>Если не ошибаюсь ShortString это массив из 128 чаров. Возможно с длиной вначале.
OV>Если точнее, то это массив на 256 байт. Первый байт это длина строки. остальные 255 — собственно сама строка. Нуля в конце строки нет, как принято в С.
Давно не юзал делфи
Ну значит так:
typedef struct
{
unsigned char len;
char content[255];
}DelphiShortString;
Re[4]: Импорт функций из делфёвой DLL
От: Аноним  
Дата: 27.06.07 11:01
Оценка:
или лучше так:
typedef struct
{
unsigned char len;
char content[255];
operator std::string()
 {
 return std::string(content, len);
 }
}DelphiShortString;
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.