Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.11.2009, 15:18   #11
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Ну, если я понял верно, то С-шная ф-ция принимает ссылку на существующую структуру и заполняет её. То есть
Код:
function qbox_GetLocation(var qb_loc: QBoxLocBtn): Integer; cdecl; external QBoxDLLFile;
А в вызывающей программе:
Код:
procedure ...
var
   QB : QBoxLocBtn;
begin
...
qbox_GetLocation(QB);
...
QB.name...
Саму структуру изменить на:
Код:
  QBoxLocBtn = record // packed здесь не надо
    id        : Integer;
    bcnt      : Integer;
    flag      : Integer;
    tag       : Integer;
		  				     
    define    : array [ 0 .. DEFINE_SIZE ] of Char; // массив
    name     : array [ 0 .. NAME_SIZE ] of Char;   // Название локации (кнопки)
    script     : array [ 0 .. SCRIPT_SIZE ] of Char;   // Скрипт локации (кнопки)
end;
Может я где-то ошибся, пусть меня поправят те, кто использует Delphi =)
И кстати, что значит макрос QBOX_API? Скорее всего в нём указан тип вызова, так что стоит к нему присмотреться )

Последний раз редактировалось netrino; 17.11.2009 в 15:24.
netrino вне форума Ответить с цитированием
Старый 17.11.2009, 18:07   #12
apromix
PHP, Delphi
Форумчанин
 
Аватар для apromix
 
Регистрация: 07.05.2008
Сообщений: 388
По умолчанию

Попробовал так сделать - не работает. Выбивает ошибку. Видимо нужно через указатели.
Мыши плакали, кололись, но продолжали жрать кактус...
мои проекты
apromix вне форума Ответить с цитированием
Старый 17.11.2009, 18:38   #13
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от apromix Посмотреть сообщение
Попробовал так сделать - не работает. Выбивает ошибку. Видимо нужно через указатели.
Нет не нужно. Какую ошибку выбивает? Очевидно, что ф-ция ожидает ссылку на структуру. Она не будет создавать новую структуру и возвращать её, она намеревается заполнять ту, которую ей передают.

Для проверки написал такое(C++):
Код:
#include <Windows.h>

struct TESTSTRUCT {
	int N;
	int Id;
	char name[30];
};

extern "C" __declspec(dllexport) int Fn(TESTSTRUCT& ts)
{
	ts.N  = 100;
	ts.Id = 200;
	lstrcpy(ts.name, "Hello, World!");

	return 0;
}

int __stdcall DllMain(HMODULE, DWORD, void*)
{
	return true;
}
(FPC в режиме совместимости с Delphi):
Код:
program Import;

type
   TESTSTRUCT = record
      N, Id : Integer;
      name  : array [0 .. 30] of char;
   end;

var
   Ts : TESTSTRUCT;

function Fn(var ts : TESTSTRUCT) : Integer; cdecl; external 'Test.dll';

begin
   Fn(Ts);
   WriteLn('N = ', Ts.N);
   WriteLn('Id = ', Ts.Id);
   WriteLn('name = ', String(Ts.name));

   ReadLn;

end.
Всё отработало как положено.

...

Кстати, ещё вопрос, в C++-ом исходнике у экспорта функции стоит extern "C"? Как вообще выглядит имя функции в таблице экспорта dll?

Последний раз редактировалось netrino; 17.11.2009 в 18:51.
netrino вне форума Ответить с цитированием
Старый 17.11.2009, 19:05   #14
apromix
PHP, Delphi
Форумчанин
 
Аватар для apromix
 
Регистрация: 07.05.2008
Сообщений: 388
По умолчанию

Ну вот как я изменил:

Код:
unit untQBoxImportFromDLL;

interface

const
  NAME_SIZE     = 128;			// Ограничение на размер имён
  DEFINE_SIZE   = 2048;		// Ограничение на размер описаний
  SCRIPT_SIZE   = 4096;		// Ограничение на размер скриптов

type
//  PQBoxLocBtn = ^QBoxLocBtn;
  QBoxLocBtn = {packed} record
    id        : Integer; // ID кнопки для GetButton(), локации для GetLocation()
    bcnt      : Integer; // GetLocation() возвращает кол-во кнопок для данной локации;
    flag      : Integer; // GetButton() возвращает flag (if flag==1, then button - visible)
    tag       : Integer; // AddLocation(), AddButton():
		  				           //	if tag == 1 then <есть скрипт>
                         //	if tag == 0 then <нет скрипта>
    define    : array [ 0 .. DEFINE_SIZE ] of Char; // массив
    name      : array [ 0 .. NAME_SIZE ]   of Char; // Название локации (кнопки)
    script    : array [ 0 .. SCRIPT_SIZE ] of Char; // Скрипт локации (кнопки)

{
    define    : PChar;   // Описание локации(кнопки)
    name      : PChar;   // Название локации (кнопки)
    script    : PChar;   // Скрипт локации (кнопки)
}
  end;

const QBoxDLLFile = 'QBox.dll';

function qbox_Init: Integer; stdcall; external QBoxDLLFile;
procedure qbox_Quit; stdcall; external QBoxDLLFile;

function qbox_LoadQuest(const fname: PChar): Integer; stdcall; external QBoxDLLFile;

//-------------- Функции управления содержанием -------------------
function qbox_GetLocation(var qb_loc: {P}QBoxLocBtn): Integer; cdecl; external QBoxDLLFile;
function qbox_GetLocCnt: Integer; stdcall; external QBoxDLLFile;


function qbox_GetButCnt(lid: Integer): Integer; stdcall; external QBoxDLLFile;

function qbox_GetVersion: PChar; stdcall; external QBoxDLLFile;
function qbox_GetAuthors: PChar; stdcall; external QBoxDLLFile;

implementation

end.
В проге:

Код:
procedure TfrmQBoxMain.Init1Click(Sender: TObject);
var
//  QA: PQBoxLocBtn;
  QA: QBoxLocBtn;
begin
  qbox_Init;
  qbox_LoadQuest(PChar('Island.qbf'));
//  New(QA);
//  QA^.name := PChar('SERG');
//  ShowMessage('GetLocation: ' + IntToStr(qbox_GetLocation(QA)));
//  ShowMessage(StrPas(QA^.name));
  qbox_GetLocation(QA);
  ShowMessage(StrPas(QA.define));
//  Dispose(QA);
end;

Выдает ошибку после завершения программы: ...access violation...
Прикрепил либу, на всякий случай, с пояснениями и заг. файлом .h
Что я не так делаю?
Вложения
Тип файла: rar QBoxDLL.rar (133.7 Кб, 9 просмотров)
Мыши плакали, кололись, но продолжали жрать кактус...
мои проекты
apromix вне форума Ответить с цитированием
Старый 17.11.2009, 19:21   #15
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Вот так должно быть правильно:
Код:
const
   NAME_SIZE   = 127;
   DEFINE_SIZE = 2047;
   SCRIPT_SIZE = 4095;

type
   QBoxLocBtn = record
      id, bcnt  : Integer;
      flag, tag : Integer;
      define    : Array [ 0 .. DEFINE_SIZE ] of Char;
      name      : Array [ 0 .. NAME_SIZE   ] of Char;
      script    : Array [ 0 .. SCRIPT_SIZE ] of Char;
   end;

function qbox_GetLocation(var QBoxLocBtn) : Integer; cdecl; external 'QBox.dll';
во всяком случае у меня ничего не вылетело и создался файл QBox_dll.log, и уж точно не моей программой
netrino вне форума Ответить с цитированием
Старый 17.11.2009, 19:42   #16
JTG
я получил эту роль
Старожил
 
Аватар для JTG
 
Регистрация: 25.05.2007
Сообщений: 3,694
По умолчанию

А вызывать - qbox_GetLocation(@QA);
пыщь
JTG вне форума Ответить с цитированием
Старый 17.11.2009, 19:46   #17
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от JTG Посмотреть сообщение
А вызывать - qbox_GetLocation(@QA);
Нет, вызывать qbox_GetLocation(QA);
Там же var стоит
netrino вне форума Ответить с цитированием
Старый 17.11.2009, 20:09   #18
apromix
PHP, Delphi
Форумчанин
 
Аватар для apromix
 
Регистрация: 07.05.2008
Сообщений: 388
По умолчанию

Пробовал и так, и сяк. Все вроде должно работать, но при завершении вызывает (как и вызывало раньше ) ошибку. И это главная проблема. И вот еще что: один раз показывает текст нормально, другой раз - короткий набор из нескольких символов (видно не попал указатель в нужное место, так кажется ). Испытал в Д-3, Д-7SE и Д-10 - везде одинаковая проблема (думал, в версию Дельфи закралась ошибка, потому так и происходит).

Вот весь исходник прикреплен, может опять что-то накосолапил?
Вложения
Тип файла: rar qb.rar (144.8 Кб, 11 просмотров)
Мыши плакали, кололись, но продолжали жрать кактус...
мои проекты

Последний раз редактировалось apromix; 17.11.2009 в 20:13. Причина: Дополнил
apromix вне форума Ответить с цитированием
Старый 17.11.2009, 20:35   #19
JTG
я получил эту роль
Старожил
 
Аватар для JTG
 
Регистрация: 25.05.2007
Сообщений: 3,694
По умолчанию

function qbox_GetLocation(var qb_loc: QBoxLocBtn) : Integer; stdcall; external QBoxDLLFile;
и ZeroMemory(@QA, sizeOf(QA)); перед qbox_Init;





Вообще, в лучших традициях сишного кода, нужно так
Код:
Type
   PQBoxLocBtn = ^TQBoxLocBtn;
   TQBoxLocBtn   = record
      id, bcnt  : Integer;
      flag, tag : Integer;
      define    : Array [ 0 .. DEFINE_SIZE ] of Char;
      name      : Array [ 0 .. NAME_SIZE   ] of Char;
      script    : Array [ 0 .. SCRIPT_SIZE ] of Char;
   end;

function qbox_GetLocation(qb_loc: PQBoxLocBtn) : Integer; stdcall; external QBoxDLLFile;

procedure TfrmQBoxMain.Init1Click(Sender: TObject);
var
  QA: PQBoxLocBtn;
begin
  New(QA);
  ZeroMemory(QA, sizeOf(TQBoxLocBtn));
  qbox_Init;
  qbox_LoadQuest(PChar('Island.qbf'));
  qbox_GetLocation(QA);
  ShowMessage(QA.define);
  qbox_Quit;
  Dispose(QA);
end;
но если с указателями не хочется возится, то, наверное, можно и переменную передавать
пыщь

Последний раз редактировалось JTG; 17.11.2009 в 20:44.
JTG вне форума Ответить с цитированием
Старый 17.11.2009, 21:07   #20
apromix
PHP, Delphi
Форумчанин
 
Аватар для apromix
 
Регистрация: 07.05.2008
Сообщений: 388
По умолчанию

Да, все работает значительно лучше и понятнее Это меня радует. Огромное спасибо Пепел Феникса, JTG и netrino! Вы очень помогли разобраться. Но почему программа сама завершает работу, слетает? В среде еще показывает ошибку ...system exception... Без Дельфи просто завершает работу. Беру в скобки try, но ничего не помогает.

Дело в том, что если я пишу так:

Код:
//  ShowMessage(QA.define);
  RE.Text := QA.define; // RE - это RichEdit
то программа моментально завершает работу. Текст даже не увидеть. Как с этой проблемой справиться?
Мыши плакали, кололись, но продолжали жрать кактус...
мои проекты

Последний раз редактировалось apromix; 17.11.2009 в 21:21. Причина: Дополнил
apromix вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка при выхове функций Bass.dll из другой DLL SalasAndriy Общие вопросы Delphi 7 21.10.2009 23:36
С++: правильный импорт dll apromix Помощь студентам 1 04.10.2009 02:28
Запуск Load.dll (бывшая Load.exe) в дереве проц-ов, Как запустить прогой на C# .dll-ку kapustin Общие вопросы .NET 10 23.09.2009 22:20
Импорт DLL в прогу cowboy Общие вопросы Delphi 5 14.04.2009 13:37
Импорт VB6 DLL в C++ DmF Общие вопросы C/C++ 1 06.03.2008 08:48