Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Проблема: Проект на C++ Buildere + DLL в MS Visual C++  (Прочитано 19914 раз)
0 Пользователей и 1 Гость смотрят эту тему.
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« : 08-10-2005 11:52 » 

Здравствуйте.
Помогите, пожалуйста, решить одну проблему.
Есть написанный в C++ Builder-e проект.

Есть написанная в MS Visual C++ DLL. Библиотека написана без использования MFC.
(Были причины писать в разных средах.)

Библиотека подключается в проекте явно с помощью LoadLibrary.
В ходе работы проекта из функции prjAddShell вызывается библиотечная функция libAddShell динамического (с использованием new) создания объектов самопального класса TShell, которые содержат потоки.

Указатели TShell* на созданные объекты передаются в проект под типом PVOID. Эти переданные указатели в проекте просто хранятся в списке объектов, т.е. никаких действий с ними не производится.

Далее из проекта из другой функции prjShellDirection вызывается очередная библиотечная функция libShellDirection управления объектами, одним из аргументов которой является указатель типа PVOID на один из объектов. В этой библиотечной функции libShellDirection происходит приведение типа PVOID к типу указателя на класс: TShell* shPtr = static_cast<TShell*>(Arg), после чего производятся некоторые действия с объектом (в т.ч., но необязательно, и его удаление вызовом delete).
В пределах функции libShellDirection все работает нормально. И возврат из этой функции в функцию prjShellDirection проета тоже происходит без проблем.

Но как только происходит выход из функции libShellDirection проекта возникает ошибка: "Access violation at address 00000009. Write of address 020C0D15." либо "Access violation at address 011835D7. Read of address FFFFFFFF."

Сперва я грешил на new/delete, т.е. на работу с памятью. Версия не подтвердилась.
Затем я просто убрал из передаваемых параметров указатель и ошибки исчезли (а функциональность, естественно, пострадала).
Также было замечено, что если все вызовы библиотечных функций делать из одной функции проекта, то ошибок не возникает (но функциональность страдает не меньше).

Кто-нибудь знает в чем может быть причина?
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 08-10-2005 13:23 » 

В книге Рихтера настоятельно не рекомендуется использовать классы в DLL библиотеках, если они будут переносится в другие среды разработок. Может быть неправльное обрашение к функциям класса. плюс несоотвествие некоторых подходов к распределению памяти. С одним из несоотвествий я сталкивался.

P.S. Здесь не принято дублировать темы в нескольких подфорумах.
« Последнее редактирование: 08-10-2005 13:27 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 08-10-2005 17:34 » 

2 Finch
Так в том-то и дело, что я не экспортировал класс из библиотеки. Я создал в библиотеке один глобальный объект, управление которым происходит с помощью четырех простых функций не являющикся методами какого-либо класса.
По поводу несоответствия подходов к выделению памяти.
Память выделяется и высвобождается только(!) внутри этого глобального объекта, т.е. в пределах библиотеки. Ситуаций, когда библиотека выделила память, а прога ее освободила (или наоборот) нет! Из библиотеки в программу на хранение передается только указатель. И тип указателя (PVOID) был выбран специально API-шный, ибо и Борланды и Микрософты должны воспринимать его абсолютно одинаково.
А за дублирование прошу прощения. Просто вопрос касается разных сред программирования и я решил, что количество прочитавших этот вопрос будет несколько больше.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #3 : 08-10-2005 18:29 » 

Память выделяется в одной куче программы. Могут быть косяки здесь. Если это твои модули, то попробуй открыть асемблерный дебагер Билдера и отследить, в какой именно точке возникают ошибки. Где именно происходит запись "Access violation at address 00000009. Write of address 020C0D15." либо "Access violation at address 011835D7. Read of address FFFFFFFF." Скорее всего при выходе из функции Билдер делает какую либо допись в эти ячейки.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 09-10-2005 09:11 » 

Дебагер я пользовал от VC++ когда отлаживал библиотеку.
Но и он показал ассемблерный код проги. Я хоть в асме и не силен, но заметил следующее.
Когда происходит выход из функции командой ret дебагер шел по адресам 0000000X, доходил до 00000009 и возникала ошибка. Но причину я не могу понять.
Насколько я помню (но могу и ошибаться) управление после выхода из ф-ции передается в вызвавшую ф-цию с одновременной очисткой стека передаваемых параметров. Но дальше этих воспоминаний никаких умозаключений построить не могу, ибо так глубоко еще никогда не копал.
Где об этом почитать можно? Пишет ли об этом Рихтер или кто-либо другой?
Записан
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 09-10-2005 09:14 » 

2 Finch
Настолько озабочен был своей проблемой, что забыл Вас поблагодарить.
Спасибо за то, что занимаетесь моей проблемой!
Записан
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 09-10-2005 09:45 » 

2 Finch
Только что загрузил проект, просмотрел, как Вы советовали, в дебагере.
Но так как для меня асм, как я уже говорил, лес достаточно темный, то я сделал скриншот.
Скриншот показывает состояние проги после выхода из управляющей ф-ции проекта (ф-ции библиотеки отработали нормально).
Посмотрите, пожалуйста. Чего там не так?

* dbg.JPG (81.49 Кб - загружено 775 раз.)
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #7 : 09-10-2005 12:55 » 

Примерно я догадываюсь в чем дело. Ты какие применил схемы возовов функций. stdcall? Судя по тому, куда у тебя выбрасывает программа, у тебя происходит или недобор стэка или перебор онного в функции библиотеки. Поэтому при выходе из процедуры не устанавливается точно адрес возврата. В адресе 0x00000009  программа не может функционировать. Так изначально заложено Виндой. Значит схема вызова функции в самой библиотеке и в твоей программе разные. Как правило на библиотечные функции устанавливают схему stdcall. Приведи отрывки программы где идет присваивание к переменной адреса функции. И кусок библиотеки, где идет определние вызываемых функций.
« Последнее редактирование: 09-10-2005 13:26 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 09-10-2005 15:55 » 

Определение ф-ций в библиотеке
//------------------------------------------------------------------------------
#define EXPORT extern "C" __declspec(dllexport)
EXPORT void Init(void);
EXPORT void Done(void);
EXPORT VoidPtr AddFolder(char * Drive, char * Path, void * ExtFunc);
EXPORT void DirectionFolder(VoidPtr SHObject, int DirectCode);
//------------------------------------------------------------------------------

Вызов одной из этих ф-ций в библиотеке
//---------------------------------------------------------------------------
EXPORT void Init(void)
  {
    FolderController = new TController;
  }
//---------------------------------------------------------------------------

Определение типов в проекте
//---------------------------------------------------------------------------
typedef PVOID VoidPtr;
typedef void (__stdcall* TLibInitFunction)(void);
typedef VoidPtr (__stdcall* TAddFolderFunction)(char * /*Drive*/,
                                                                    char * /*Path*/,
                                                                    void * /*ExtFunc*/);
typedef void (__stdcall* TDirectionFolderFunction)(VoidPtr /*SHObject*/,
                                                                       int /*DirectCode*/);
//---------------------------------------------------------------------------

Определение переменных в проекте
//---------------------------------------------------------------------------
TLibFunction Init, Done;
TAddFolderFunction AddFolder;
TDirectionFolderFunction DirectionFolder;
//---------------------------------------------------------------------------

Инициализация ф-ций в проекте:
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  ShellLib = LoadLibrary("shellib.dll");
  Init = (TLibFunction)GetProcAddress(ShellLib, "Init");
  Done = (TLibFunction)GetProcAddress(ShellLib, "Done");
  AddFolder = (TAddFolderFunction)GetProcAddress(ShellLib, "AddFolder");
  DirectionFolder = (TDirectionFolderFunction)GetProcAddress(ShellLib, "DirectionFolder");
  Init();
}
//---------------------------------------------------------------------------

Вызов ф-ций в проекте
//---------------------------------------------------------------------------
VoidPtr SHObject1;
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  SHObject1 = AddWatchedFolder(Edit1->Text, ExtFunc);
  DirectionFolder(SHObject1, 1);
}
//---------------------------------------------------------------------------

ExtFunc - указатель на функцию проекта, которую при определенных условиях должны вызывать потоки объектов самопального класса TShell.
В принципе вызов этой ф-ции происходит тоже нормально.
Но на всякий случай приведу и ее описание.

Описание в проекте
//---------------------------------------------------------------------------
void __stdcall ExtFunc(char * Str, void * SHObject, bool &Abort, ULONG Attrib);
//---------------------------------------------------------------------------

Определение типа в библиотеке
//---------------------------------------------------------------------------
typedef void __stdcall TExternalFunction(char * /*pObjectName*/,
                                                        void * /*SHObject*/,
                                                        bool & /*Abort*/,
                                                        ULONG /*Attrib*/);
//---------------------------------------------------------------------------

Приведение типа в библиотеке
//---------------------------------------------------------------------------
    efExtFunc = reinterpret_cast<TExternalFunction *>(extFunc);
//---------------------------------------------------------------------------

И, соответственно, вызов в библиотеке
//---------------------------------------------------------------------------
efExtFunc(pObjectName, SHObject, Abort, Attrib);
//---------------------------------------------------------------------------
Записан
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 09-10-2005 15:58 » 

Небольшое уточнение
В ф-ции AddWatchedFolder(Edit1->Text, ExtFunc) сперва происходит расщепление Edit1->Text на подстроки, а потом вызывается AddFolder.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #10 : 09-10-2005 16:07 » 

Код:
#define EXPORT extern "C" __declspec(dllexport)
EXPORT void Init(void);
EXPORT void Done(void);
EXPORT VoidPtr AddFolder(char * Drive, char * Path, void * ExtFunc);
EXPORT void DirectionFolder(VoidPtr SHObject, int DirectCode);
Код:
typedef void (__stdcall* TLibInitFunction)(void);
typedef VoidPtr (__stdcall* TAddFolderFunction)(char * /*Drive*/,
                                                                    char * /*Path*/,
                                                                    void * /*ExtFunc*/);
typedef void (__stdcall* TDirectionFolderFunction)(VoidPtr /*SHObject*/,
                                                                       int /*DirectCode*/);
У тебя разные определения вызовов функции. Библиотеку по новой откомпилируй. Но напиши так:
Код:
#define EXPORT extern "C" __declspec(dllexport)
EXPORT void __stdcall Init(void);
EXPORT void __stdcall Done(void);
EXPORT VoidPtr __stdcall AddFolder(char * Drive, char * Path, void * ExtFunc);
EXPORT void __stdcall DirectionFolder(VoidPtr SHObject, int DirectCode);
Чтобы не было проблем с именами, подключи к проекту библиотеки Def файл
Код:
LIBRARY     Temple                       

DESCRIPTION 'Probe DLL'

EXPORTS
          Init                  @1
          Done               @2
          AddFolder        @3
          DirectionFolder  @4
Имя файла должно быть Название_твоей_Библиотеки.def
В поле LIBRARY Укажи имя библиотеки заместо Temple
« Последнее редактирование: 20-12-2007 19:40 от Алексей1153++ » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 09-10-2005 16:16 » 

Забыл самое главное!
Когда происходит вызов такой:
//-----------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  SHObject1 = AddWatchedFolder(Edit1->Text, ExtFunc);
  DirectionFolder(SHObject1, 1);
}
//-----------------------------------------------------------------------------
никаких ошибок.

А вот если далее мы сделаем вызов из другой ф-ции
//-----------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
  if (Folder1 != NULL)
    {
      DirectionFolder(Folder1, 4);
      Folder1 = NULL;
    };
  if (Folder2 != NULL)
    {
      DirectionFolder(Folder2, 4);
      Folder2 = NULL;
    };
}
//---------------------------------------------------------------------------
вылазит ошибка.

Только что сделал так как Вы советуете:
EXPORT void __stdcall Init(void);

Ошибка прет уже на этапе вызова ф-ции Init.

shellib.def файл у меня есть:
//---------------------------------------------------------------------------
LIBRARY      shellib.dll
EXPORTS      Init
                   Done
                  AddFolder
                  DirectionFolder
//---------------------------------------------------------------------------

Там, правда, нет номеров у функций. Но Рихтер тоже не рекомендует их употреблять.
Записан
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 09-10-2005 16:23 » 

Я, конечно, понимаю, что есть обходной вариант.
Сделать в библиотеке небольшой динамический список.
При создании объектов с потоками их адреса хранить в этом списке, а во внешний мир передавать какой-нибудь идентификатор тип int, а управление этими объектами производить по этим идентификаторам.
Тогда гарантированно ошибок не будет.
Но, блин, интересно почему после так происходит именно со ссылками?
Записан
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 09-10-2005 16:40 » 

Однако, погорячился я на счет "гарантированно"!
Выскакивает ошибочка!

PS
Фразу "Но, блин, интересно почему после так происходит именно со ссылками?"
надо читать так "Но, блин, интересно почему так происходит именно со ссылками?"
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #14 : 09-10-2005 16:50 » 

Таже самая ошибка выскочила? Или другая когда вызываеш Init. Жалко нету сейчас билдера под рукой. На растоянии ничего сказать не смогу.
« Последнее редактирование: 09-10-2005 16:56 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #15 : 09-10-2005 16:55 » 

Адрес стал 00000013. А в остальном все так же не хорошо.
Записан
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 09-10-2005 17:12 » 

Вообще лучше расскажу предысторию!
Мне нужно было, чтобы несколько потоков следили за несколькими папками (по правилу "один поток - одна папка"). Хотел было сделать потоки в проекте. Но потом вспомнил об организации подключения библиотек (в частности об общем адресном пространстве). И понял, что все потоки будут создавать классы, которые будут теряться и память из-под них высвобождаться не будет.
Потом у Рихтера прочитал про TLS (Thread Local Storage {или как-то так}). Но идея мне по вкусу не пришлась и решил я делать вот как.
Прога создает несколько объектов. Каждый объект вызывает библиотечную ф-цию по созданию еще одного объекта, который, в свою очередь, владеет объектом-потоком! Адреса этих объектов с потоками передаются из библиотеки в прогу и сохраняются в инициировавших всю эту процедуру объектах.

Сказано - сделано.
Есть библиотека. Есть тестовая прога.
При создании библиотечного объекта с потоком и запуске его:
//-----------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  SHObject1 = AddWatchedFolder(Edit1->Text, ExtFunc);
  DirectionFolder(SHObject1, 1);
}
//-----------------------------------------------------------------------------
ошибок не возникает - поток поточит и следит за папками.

//-----------------------------------------------------------------------------
Правда здесь тоже не без вывертов.
Функция потока - это статичный метод объекта-владельца.
Параметр ф-ции потока - ссылка на сам объект владелец.
Вот как это происходит:

DWORD WINAPI c_Shell::ThreadFunc(void * pArg)
  {
    TShellPtr tsShell = reinterpret_cast<TShellPtr>(pArg);
    tsShell->Monitoring();
    tsShell = NULL;
    return 0; //пусть всегда будет ноль
  }

Ф-ция tsShell->Monitoring() это цикл, выход из которого происходит по некоторому Event-у.

//-----------------------------------------------------------------------------

Но как только хочется мне поток убить нажатием другой кнопки - поток убивается и вылезает ошибка!

Я, знаете ли, как Сухов: "Хотелось бы помучиться!" Улыбаюсь))
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #17 : 09-10-2005 17:59 » 

Процессор наверно у тебя загружен на все 100. У винды есть славная функция по мониторингу папок FindFirstChangeNotification которая выдаст Handle. Затем только поток останется повесить на функцию WaitForSingleObject. Которая прекратит работу потока, до первого изменения. Затем только останется Вызвать FindNextChangeNotification чтобы возобновлять мониторинг. Ну естественно FindCloseChangeNotification чтобы прекратить мониторинг и закрыть Хэндл.

Да кстати тоже самое можно сделать и на Билдере. У него тоже есть объекты-потоки. Предположение, что косяк с разделением памяти смутно остается.
В асме подсчитай количество байт загнаных Push и взятых Pop из стэка. При входе в функцию, в самой функции и при выходе. Если оно равно. Значит стэк кто то у тебя бомбит. Если библиотека не отлажена в VC может быть ты переходиш граници диапазонов.
« Последнее редактирование: 09-10-2005 18:10 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #18 : 09-10-2005 18:14 » 

Это ф-ция мониторинга.
Здесь и используются эти нотификации.
Кстати. Пример взят из MSDN и просто доработан.
//------------------------------------------------------------------------------
void c_Shell::Monitoring(void)
  {
    DWORD dwWaitStatus;
    bool flag = true;
    // Предварительно должен быть инициализирован массив dwChangeHandles[]
    while ((flag) && (!IfTerminateMonitoring))
      {
        // Wait for notification.
        dwWaitStatus = WaitForMultipleObjects(3,
                                              dwChangeHandles,
                                              FALSE,
                                              INFINITE); //в момент изменения
        switch (dwWaitStatus)
          {
            case WAIT_OBJECT_0:
              { // произошло изменение среди файлов
                GetFolderItems(NULL,
                                Pointers.lpsfFolder,
                                (SHCONTF)(SHCONTF_NONFOLDERS
                                          | SHCONTF_INCLUDEHIDDEN));
                if (!FindNextChangeNotification(dwChangeHandles[0]))
                  flag = false;
              }; break;
            case WAIT_OBJECT_0 + 1:
              { // произошло изменение среди папок
                GetFolderItems(NULL,
                                Pointers.lpsfFolder,
                                (SHCONTF)(SHCONTF_FOLDERS
                                          | SHCONTF_INCLUDEHIDDEN));
                if (!FindNextChangeNotification(dwChangeHandles[1]))
                  flag = false;
              }; break;
            case WAIT_OBJECT_0 + 2:
              { // пришло сообщение о завершении работы
                flag = false;
                IfTerminateMonitoring = true;
                ExitThread(0);
              }; break;
        };
      };
  }
//------------------------------------------------------------------------------

Загрузку проца я проверял - при работе двух потоков увеличивается всего на два процента!
Тестирую программу на компутере Pentium-233 MMX (разогнан до 250MHz), 128 Мб ОЗУ, Винда 98-я.
В среднем при обычной работе загрузка проца составляет процентов 15-20.
Компутер такой слабенький для того, чтобы чувствовалась различного рода оптимизация по скорости работы.

Правда вся славность функции FindFirstChangeNotification ограничивается ее ограничениями: я никак (пока) не добился того, чтобы мне возвращалось имя измененного объекта папки.
Вот в WinNT есть для такого рода занятий действительно славная ф-ция: ReadDirectoryChangesW (или как-то похоже). На нее в MSDN-е даже отдельный пример дан. Работает она с помощью CreateCompletionPort (или как-то похоже).
Но, блин, в Вин'98 она не поддерживается, а вот на CreateCompletionPort компилятор под Вин'98 не ругнулся. Хотя MSDN говорит, что и она поддерживается только в NT.
« Последнее редактирование: 20-12-2007 19:42 от Алексей1153++ » Записан
Алик
Постоялец

kz
Offline Offline

« Ответ #19 : 09-11-2005 03:23 » 

Почитал тему, посмотрел приведенные коды.
думаю, проблема (Access Violation) - именно в разных конвенциях вызова: в проекте прототипы функций объявлены _stdcall, а в длл - нет и по умолчанию подчиняются правилам _cdecl

direktorSan, разобрался с проблемой?
Записан
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 10-11-2005 13:09 » 

Нет! Не разобрался! Жаль
Но я уже пытался экспортить из библиотеки ф-ции как __stdcall.
Ошибки перли на стадии получения ссылок на ф-ции библиотеки.
Проект, по некоторым причинам, заморожен на несколько месяцев.
Думаю, потом, когда вернусь к нему, найду либо решение либо обходной путь!
Спасибо за ответы!
Записан
Алик
Постоялец

kz
Offline Offline

« Ответ #21 : 10-11-2005 13:15 » 

Интересно,
а что за ошибки?
имеется ввиду, GetProcAddress ошибку дает? а GetLastError что говорит?
Записан
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 11-11-2005 04:33 » 

Да. Ошибку кидал GetProcAddress.
Однако GetLastError-ом не смотрел.
Сейчас я уже не помню что за номер ошибки.
Посмотрю на выходных и тогда отвечу.
Записан
direktorSan
Удачи!
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #23 : 13-11-2005 08:48 » 

Ур-р-р-р-а-а-а! Заработала!

Разобрался!

Дело было так.

Установил я экспорт ф-ций в __stdcall.
При попытке возвратить адрес GetProcAddress выдал ошибку "Не найдено процедуры с таким именем".

Тогда вспомнил, что Рихтер об этом что-то писал.
Поискал и нашел следующее:
"Тогда компилятор Microsoft искажает имя С-функции: впереди ставит знак подчеркивания, а к концу добавляет суффикс, состоящий из символа @ и числа байтов, передаваемых функции в качестве параметров." (Д.РИХТЕР, "Создание эффективных WIN32-приложений")

Это он говорил про __stdcall-функции DLL написанных в VC++, которые потом будут вызываться из EXE-шников, созданных другими компиляторами.

Там же предложено два способа борьбы.

1. DEF-файл с разделом EXPORTS.
У меня он почему-то не работал. Хотя проверил везде, где только мог. Наверное там, где не смог проверить и осталась какая-то галочка. Улыбаюсь

2. #pragma comment(linker, "/export:Init=_Init@0")
Вставляя такую строку в h-файл библиотеки мы указываем компилятору, что нужно экспортировать не только имя _Init@0, но и равное ему имя Init.
Вот с таким способом все заработало!

Всем спасибо.
Записан
zakalibit
Гость
« Ответ #24 : 20-02-2006 16:49 » 

poprobui "implib -m <libfile name to generate> <VC++ DLL name>", ne pomniu tochno esli -m nado, posmotri v help u implib, tam esti switch otveceaiusii za name mangling, potm prosto impotiruies .lib v svoi C++ Builder proect i vse, igolova ne bolit o vseh konversiah
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines