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

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

il
Offline Offline
Пол: Мужской
Бодрый птах


« : 19-08-2005 06:06 » 

Вопрос немного странный.

Просто я не делал этого раньше в таком вот виде.

Есть программа, в которой есть некии функции.
К ней пишется подключаемая динамически DLL-ка...

У программы есть набор своих билиотек, которые тоже подключаются в runtime

Нужно, что бы при написании DLL динамической, можно было использовать DLL программы как набор управляющих функций...

Примерно так.

Нпример у программы есть тип жанных в виде void * который создается динамически. Надо что бы в момент runtime он был сформирован и передан в DLL стороннюю как параметр определенной структуры и размера, заданный в DLL.

Таким образом я должен передать с помощью SDK и ее функции....

Но при подключении SDL DLL к DLL сторонней создается еще один instance и получается глупость...


Как это обойти.
Записан

А птичку нашу прошу не обижать!!!
Hooter
Опытный

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

« Ответ #1 : 19-08-2005 09:32 » 

не очень понятно, если честно Жаль
 
Есть программа, в которой есть некии функции.
К ней пишется подключаемая динамически DLL-ка...
У программы есть набор своих билиотек, которые тоже подключаются в runtime
Нужно, что бы при написании DLL динамической, можно было использовать DLL программы как набор управляющих функций...

Если я правильно понял, то нужно передавать некие данные из программы или DLL в другую DLL, которая подключается неизвестнно когда?..

Если так, то в любой момент времени из программы или DLL можно узнать подключена ли какая-то DLL с помощью GetModuleHandle (нужно знать имя DLL). Если модуль подключен, то можно получить адрес нужной функции с помощью GetProcAddress (нужно знать имя функции), вызывать эту функцию и передавть в нее данные (нужно знать семантику функции).

Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #2 : 19-08-2005 09:40 » 

Hooter - ты правильно понял в принципе.

Но немного не так.
я хочу в DLL созаваемой не мной предоставить инетрфейс в виде готовых библиотек к работающей программе, например к серверу.

Однако вызов не должен быть по семантике, а желательно стандартное подключение...
Записан

А птичку нашу прошу не обижать!!!
Hooter
Опытный

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

« Ответ #3 : 19-08-2005 09:48 » 

я хочу в DLL созаваемой не мной предоставить инетрфейс в виде готовых библиотек к работающей программе, например к серверу.
Однако вызов не должен быть по семантике, а желательно стандартное подключение...
Что значит стандартное подключение? Если не по семантике, тогда как? Перефразируй, плз.

Ты собираешься создать набор библиотек, которыми будет пользоваться кто-то другой?
Записан
npak
Команда клуба

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

« Ответ #4 : 19-08-2005 09:58 » 

Гром, может быть, ты хочешь, чтобы другое приложение линковалось с набором небольших библиотек, которые при необходимости грузились бы в память процесса автоматически?

Если это так, то тебе нужны import libraries.  Например, kernel32.lib, с которой линкуются все приложения, использующие win32 API, на самом деле не содержит реального кода, только заглушки, которые при вызове функций загружают kernel32.dll и передают управление реализации в dll.

import library генерируются автоматически и складывается в output каталог проекта DLL.  Import libraries поставляются в составе SDK
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Hooter
Опытный

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

« Ответ #5 : 19-08-2005 10:10 » 

Да, Гром, поясни, плз.
Если тебе действительно нужна линковка с помощью import libraries, то причем здесь тогда "подключение в runtime"?
У программы есть набор своих билиотек, которые тоже подключаются в runtime
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #6 : 20-08-2005 18:38 » 

Нет так не пойдет
Давайте я подробнее нарисую....

1. Есть программа А которую пишет программист А1
2. Программа умеет подгружать к себе типовую DLL Б не в момент сборки как это происходит чаще всего, а с помощью LoadLibrary.

Вызывается набор типовых ф-ий с известными параметрами.

Для этого предусмотрен механизм инициализации с передачей указателей в программу.

3. Программист Б1 пишет типовую билиотеку дабы ее подключить.

При этом у программиста Б1 нет ни кода программы А ни связи с программистом А1.

В базовую поставку программы А входят стандартный набор библиотек динамически слинкованных с программой. Они должны осуществлять некий (неважно какой) набор функциональности для программы А и библиотеки Б

Программист Б1 должен получить стандартный h файл и lib файл, стандартно слинковать это все динамически или статически, как ему удобно.


Процедура работы такова....

При нажатии на кнопку программы А запускается нужная функция библиотеки Б которая вызовами нужными программисту Б1 запускает работу того интерфейса, который упомянут ранее.

Теперь проблема.

Если я подключаю балиотеку с помощью LoadLibrary я создаю ее экземпляр, и параллельно экземпляр билиотек которые или которая, вызваются программистом Б1.
Однако эти же библиотеки уже были загружены в память при старте программы А....

Как сделать так, что бы и то и другое использовало единый экземпляр билиотек и в программе А и в приложенной библиотеке Б для нормального обмена данными и работе в единой среде. Ведь и то и то - это одна аппликация....

Записан

А птичку нашу прошу не обижать!!!
Finch
Спокойный
Администратор

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


« Ответ #7 : 20-08-2005 18:55 » 

Гром, честно говоря не совсем допонял.
Винда сама регулирует, чтобы библиотека загружалась в единственном экземпляре. На все приложения, которые ее используют. Можеш попробывать. В одном и том приложении вызвать загрузку дважды одной и той же библиотеки. Тебе придет один и тот же hInstance библиотеки.

Код:
#include <windows.h>
int main()
{
HINSTANCE lib1=LoadLibrary("KPAPI32.DLL");
HINSTANCE lib2=LoadLibrary("KPAPI32.DLL");
return 0;
}
У меня после выполнения lib1 и lib2 равны 0x10000000

Если ты используеш библиотеку в двух разных приложениях, тогда надо просто согласовать адреса загрузки всех библиотек используемых в приложениях.
« Последнее редактирование: 20-08-2005 19:06 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

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

WWW
« Ответ #8 : 20-08-2005 19:36 » 

Проблема, как я ее понимаю, в том, чтобы твоя динамически подгружаемая библиотека импортировала адреса ф-ий из других библиотек, уже подгруженных главным модулем. Так?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #9 : 20-08-2005 20:07 » 

Второй пост - да и не только....
Я не очень понимаю. Я же гружу библиотку второй раз... и опять таки в библиотеке - думаешь и данные и все будет одинаковое ?

Записан

А птичку нашу прошу не обижать!!!
Finch
Спокойный
Администратор

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


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

Гром ты грузиш библиотеку. Винда сначало проверяет, не загружена ли она в данном приложении. Если да, то возрашает адрес той библиотеки. Естественно все адреса функций будут на тех же местах. 
Посмотри 20 главу книги Рихтера "Виндовс-для проффесионалов". В ней говорится, что при повторной загрузке не выполняется вызов функции BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, PVOID fImpLoad)
Следовательно, если в ней ты иницилизируеш переменные, то они не будут иницилизированы повторно.
« Последнее редактирование: 20-08-2005 20:37 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

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

WWW
« Ответ #11 : 20-08-2005 20:31 » 

Во втором: "правильно, но не так...".

Основной модуль загружает динамическую библиотеку и, когда он зывывает ее ф-ии, они находятся в его адресном пространстве. Тут и код, и данные должны быть доступны. Т.е., указатели валидны, а адреса ф-ий ты можешь получить вручную. Чего еще не хватает?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #12 : 21-08-2005 06:15 » 

Finch - ну не - не надо меня учить азам Улыбаюсь

Суть проста, я вызываю библиотеку из библиотеки. А не два раза из одной и той же аппдикации.
Кроме того ты путаешь коллчиество загруженных dll и колличество инстансов билиотеки.

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

RXL - я не уверен, что подгрузка явная библиотеки не даст мне эффект второго инстанса в моем случае древовидного вызова, если кто уже делал, поделитесь данными или сделайте ксперимент у кого есть время.
Мне важно точно знать, а не "по идее" , "по идее" я с вами всеми согласен.
Записан

А птичку нашу прошу не обижать!!!
Finch
Спокойный
Администратор

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


« Ответ #13 : 21-08-2005 14:00 » 

Быстрый пример:

Первая библиотека Lib1
Lib1.h
Код:
#ifndef DLLLOADAPI
#define DLLLOADAPI extern "C" __declspec(dllimport)
#endif

//-------------------------------------------------------------------
DLLLOADAPI  int __stdcall SetQuery(void);

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

Lib1.cpp
Код:
#include <windows.h>

#define DLLLOADAPI extern "C" __declspec(dllexport)
#include "Lib1.h"


HINSTANCE hinstan;

//-------------------------------------------------------------------
int  __stdcall SetQuery(void)
{
return (int) hinstan;
}

BOOL WINAPI DllMain(HINSTANCE hinst, unsigned long reason, void*)
{

switch( reason )
   {
case DLL_PROCESS_ATTACH:
  hinstan=hinst;
           // Initialize once for each new process.
           // Return FALSE to fail DLL load.
           break;

      case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

      case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

      case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

Вторая Библиотека Lib2
Lib2.h
Код:
#ifndef DLLLOADAPI
#define DLLLOADAPI extern "C" __declspec(dllimport)
#endif

//-------------------------------------------------------------------
DLLLOADAPI  int __stdcall SetQuery(void);

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

Lib2.cpp
Код:
#include <windows.h>

#define DLLLOADAPI extern "C" __declspec(dllexport)
#include "Lib2.h"


HINSTANCE hinstan;

//-------------------------------------------------------------------
int  __stdcall SetQuery(void)
{
return (int) hinstan;
}

BOOL WINAPI DllMain(HINSTANCE hinst, unsigned long reason, void*)
{

switch( reason )
   {
case DLL_PROCESS_ATTACH:
  hinstan=LoadLibrary("Lib1.Dll");
           // Initialize once for each new process.
           // Return FALSE to fail DLL load.
           break;

      case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

      case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

      case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}


Обший Def Файл
Library.def
Код:
LIBRARY     Library                       

DESCRIPTION 'Probe DLL'

EXPORTS
            SetQuery                      @1

Ну сам исполняемый модуль
Main.cpp
Код:
#include <windows.h>
typedef int  (__stdcall *TSetQuery)(void);
int main()
{

HINSTANCE lib1=LoadLibrary("Lib1.dll");
TSetQuery sq1=GetProcAddress(lib1,"SetQuery");
int ins1=sq1();
HINSTANCE lib2=LoadLibrary("Lib2.dll");
TSetQuery sq2=GetProcAddress(lib2,"SetQuery");
int ins2=sq2();
        return 0;
}

После исполнения переменные принимают значения:
lib1  = 0x10000000
sq1  = 0x1000100a
ins1 = 0x10000000
lib2  = 0x00350000
sq2  = 0x0035100a
ins2 = 0x10000000
« Последнее редактирование: 20-12-2007 16:11 от Алексей1153++ » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #14 : 21-08-2005 15:12 » 

Давай проще...
1. lib1.dll должна иметь функции

Send ()
{
    SendData (x);
}

SendX( int _x)
{
    x = _x;
}




lib2.dll должна иметь функцию
Run()
{

SendX(10);

}



Во второй билиотеке есть вызов


#include "lib1.h"
 и никаких LoadLibrary полное явное подгружение через lib1.lib .

В программе идет так


#include "lib1.h"

typedef void (void) /* указатель на фукцию типа Run() из lib2 полностью не пишу - время нет */

main()
{
hInstance = LoadLibrary(Lib2);

/* Вызов функции Run() с помощью поинтера */

Send();

}


Должна быть отослана цифра 10.



Разница с твоим описанием в том, что я подгружаю программой и первую и вторую билиотеку. Первую с помощью обычного метода в момент линковки - вторую динамически через loadLibrary.

А сама библиотека тоже должна во время линковки подгрузить себе первую. А вот потом, потом из программы будет вызвана функция второй библиотеки в которой та с помощью вызова функций первой установит в памяти нужные значения и потом программа сделает нужный посыл, нужных данных в нужном направлении....


Идея такая поставлять программу с SDK с помощью которого будет писаться некий кит под себя для среды в котором с помощью SDK будет написаны нужные функции....

Вот так вот.
А так как ты пишешь вообще непонятно.
С какой радости в разных билиотеках одноименная функция принимаеит один и тот же адресс - на лице явная ошибка....
Или я чего то не понял....




Записан

А птичку нашу прошу не обижать!!!
Finch
Спокойный
Администратор

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


« Ответ #15 : 21-08-2005 15:32 » 

Цитата
С какой радости в разных билиотеках одноименная функция принимаеит один и тот же адресс - на лице явная ошибка....
Ты можеш ткнуть пальцем где имеется один и тот же адрес двух разных функций.
sq1  = 0x1000100a
sq2  = 0x0035100a
Это вообше то разные цифры. Или я уже не могу читать цифры?
Даже если бибилиотека грузится по умолчанию. Виндовс сама вызывает функцию LoadLibrary. Дж. Рихтер "Виндовс для проффессионалов"
Цитата
При его запуске загрузчик операционной системы выполняет следующие операции

1. Загрузчик операционной системы создает виртуальное адресное пространство для нового процесса и проецирует па пего исполняемый модуль.
2. Далее загрузчик анализирует раздел импорта, находит все необходимые DLLмодули и тоже проецирует на адресное пространство процесса. Заметьте, что DLL может импортировать функции и переменные их другой DLL, а значит, у нее может быть собственный раздел импорта. Заканчивая подготовку процесса к работе, загрузчик просматривает раздел импорта каждого модуля и проецирует все требуемые DLL-модули на адресное пространство этого процесса. Как видите, на инициализацию процесса может уйти довольно длительное время.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Finch
Спокойный
Администратор

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


« Ответ #16 : 21-08-2005 16:23 » 

Вот примерно по твоим условиям:

Первая библиотека Lib1.Dll
Lib1.h
Код:
#ifndef DLLLOADAPI
#define DLLLOADAPI extern "C" __declspec(dllimport)
#endif

//-------------------------------------------------------------------
DLLLOADAPI  int __stdcall GetX(void);
DLLLOADAPI  void  __stdcall SetX(int _x);
//-------------------------------------------------------------------

Lib1.cpp
Код:
#include <windows.h>

#define DLLLOADAPI extern "C" __declspec(dllexport)
#include "Lib1.h"


int x;

//-------------------------------------------------------------------
void  __stdcall SetX(int _x)
{
x=_x;
}

int __stdcall GetX(void)
{
return x;
}

BOOL WINAPI DllMain(HINSTANCE hinst, unsigned long reason, void*)
{

switch( reason )
   {
case DLL_PROCESS_ATTACH:
x=0;
           // Initialize once for each new process.
           // Return FALSE to fail DLL load.
           break;

      case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

      case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

      case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

Lib1.Def
Код:
LIBRARY     Lib1                        

DESCRIPTION 'Probe DLL'

EXPORTS
    SetX                      @1
    GetX                      @2

Вторая библиотека Lib2

Lib2.h
Код:
#ifndef DLLLOADAPI
#define DLLLOADAPI extern "C" __declspec(dllimport)
#endif

//-------------------------------------------------------------------
DLLLOADAPI  void  __stdcall SetX(int _x);

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

Lib2.cpp
Код:
#include <windows.h>

#define DLLLOADAPI extern "C" __declspec(dllexport)
#include "Lib2.h"

typedef void  (__stdcall *TSetX)(int _x);

HINSTANCE lib1;
TSetX sx;

//-------------------------------------------------------------------
void  __stdcall SetX(int _x)
{
sx(_x);
}

BOOL WINAPI DllMain(HINSTANCE hinst, unsigned long reason, void*)
{

switch( reason )
   {
case DLL_PROCESS_ATTACH:
  lib1=LoadLibrary("Lib1.Dll");
  sx=(TSetX ) GetProcAddress(lib1,"SetX");
  sx(10);

           // Initialize once for each new process.
           // Return FALSE to fail DLL load.
           break;

      case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

      case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

      case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

Lib2.Def
Код:
LIBRARY     Lib2                       

DESCRIPTION 'Probe DLL'

EXPORTS
            SetX                      @1

Ну и сам исполняемый файл

Main.cpp
Код:
#include <windows.h>
#include "Lib1.h"

int main()
{
int x=GetX();
HINSTANCE lib2=LoadLibrary("Lib2.dll");
x=GetX();

return 0;
}

До загрузки Lib2.dll     x = 0
После загрузки lib2.dll x = 10
« Последнее редактирование: 20-12-2007 16:13 от Алексей1153++ » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #17 : 21-08-2005 16:37 » 

ins1 = 0x10000000
ins2 = 0x10000000

Я это имел ввиду Улыбаюсь

А вот за полный пример спасибо...
Итак получаем, что в обоих случаях мы имеем одинаковые данные и один общий экземпляр библиотеки.

Единственное, что я вижу, что в приведенном тобой тексте нет упоминания LoadLibrary.

Насколько я помню вызов библиотеки с помощью функции LoadLibrary не одинаков для случаев когда есть h файл и когда нету его.

В первом случае семантика функций известна, и имеется адреса экспортируемых функций которые проходят через нас. Во втором слчае вызов идет только по адресу который заранее при линковке неизвестен....

Я просто уже давно в винде не работал так глубоко - кое что подзабыл - ты уж прости не злись Улыбаюсь
Записан

А птичку нашу прошу не обижать!!!
npak
Команда клуба

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

« Ответ #18 : 22-08-2005 10:58 » 

Если под "библиотекой" подразумевается DLL, то при соблюдении некоторых предосторожностей в адресное просторанство процесса действительно отображается только один экземпляр DLL и создаётся один экземпляр данных.  Главное, что надо соблюдать -- чтобы DLL грузились из одного файла.  Если при разных вызовах LoadLibrary будут найдены разные файлы, то загружены будут разные DLL с одним именем.  Например,

Код:
#include <windows.h>
#include <stdio.h>

#define PATH1 "msvcrt40"
#define PATH2 "c:\\WINNT\\ServicePackFiles\\i386\\msvcrt40.dll"

int main(int argc, char * argv[])
{
    HMODULE hmod2;
    HMODULE hmod1 = LoadLibrary(PATH1);
    if (hmod1 == NULL)
    {
        printf("Failed to load module %s, error %d\n", PATH1, GetLastError());
        return 1;
    }
    printf("Loaded module %s\n", PATH1);

    hmod2 = LoadLibrary(PATH2);
    if (hmod2 == NULL)
    {
        printf("Failed to load module %s, error %d\n", PATH2, GetLastError());
        return 1;
    }
    printf("Loaded module %s\n", PATH2);

    return 0;
}

В первом LoadLibrary будет загружен модуль из c:\winnt\system32\msvcrt40.dll, во втором случае будет загружен модуль из c:\WINNT\ServicePackFiles\i386\msvcrt40.dll.  Системе наплевать, что эти два модуля побитово совпадают, раз они найдены в разных местах, то определяются как разные и, соответственно, оба загружаются.

Для того, чтобы избежать подобной проблемы, надо использовать одну и ту же строку при загрузке библиотеки.  Один из способов обеспечить это -- не вызывать LoadLibrary самостоятельно, а пользоваться import library, .lib файлом, который автоматически генерируется компилятором при сборке DLL.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
npak
Команда клуба

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

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

LoadLibrary и GetProcAddress работают одинаково как при наличии  , так и при отсутствии #include "my.h" в исходниках.  Эти функции работают со путями и строками и не вкладывают никакой зависящей от приложения семантики в свои действия. 
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #20 : 22-08-2005 11:24 » 

Самый прикол, что в случае работы с Load Library невозможно грузить функции описанные по стандарту С++ только С. Внутре вызывай че хошь а так не моги, так что видимо отменяется вся така байда....

Хотя соблазна велик - хотел бы динамически грузить функции с знанием структур и имен файлов.
Записан

А птичку нашу прошу не обижать!!!
Finch
Спокойный
Администратор

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


« Ответ #21 : 22-08-2005 11:47 » 

Гром, а кто тебе мешает сделать примерно как я.
Код:
typedef int  (__stdcall *TSetQuery)(void);
.....................
TSetQuery sq1=GetProcAddress(lib1,"SetQuery");
int ins1=sq1();

Шаблоны всех фукнкций опредилить в заголовочном файле. А потом только останется иницилизировать переменные, как функция. И работать.

Записан

Не будите спашяго дракона.
             Джаффар (Коша)
npak
Команда клуба

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

« Ответ #22 : 22-08-2005 12:29 » 

С++ имена грузить возможно, только надо знать, как они трансформируются (name mangling).
Если не хочется связываться с name mangling, то надо пользоваться import library: при построении import library компилятор генерирует код, который знает, какое имя грузить из DLL
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Finch
Спокойный
Администратор

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


« Ответ #23 : 22-08-2005 12:40 » 

Если в проект библиотеки вставлять Def файлы. То компилятор не переворачивает имена stdcall формат.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #24 : 22-08-2005 15:25 » 

Есть маленький ньюанс во всем этом.
Если я хочу это использовать - то я должен сделать так, что бы создателю DLL не пришлось бы думать как писать. Он должен использовать все просто - создал библиотеку отдал мне - все прогрузилось.


Вопрос такой, есть у меня только dll файл - без заголовочного и деф и либ файла.
Импорт библиотеки import library идет по либ файлу. Простая подгрузка идет по заголовочному, я должен грузить простым способом.
Итак Finch я попробую с stdcall скажу о результатах.
Записан

А птичку нашу прошу не обижать!!!
Finch
Спокойный
Администратор

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


« Ответ #25 : 22-08-2005 16:18 » 

Гром посмотри тему https://forum.shelek.ru/index.php/topic,3621.0.html . Там npak Расписал как получить .lib  файл. Также можно получить имена функций. А вот с параметрами функций будут проблемы, если вообше ничего не известно о библиотеке.
Но по идее говоря, если Вы разрабатываете проект вместе, то должны согласовывать интерфейс экспортируемых функций. Поэтому я думаю не должно быть проблем с .lib и .h файлами.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #26 : 22-08-2005 19:08 » 

Вить - неужели ты думаешь что я не умею собрать либ файл???

Ч написал условие работы причем ты знаешь какой.
Записан

А птичку нашу прошу не обижать!!!
Anchorite
Гость
« Ответ #27 : 22-08-2005 19:22 » 

Гром, ты забыл о такой вещи как COM. Для своих нужд ты можешь использовать не самого его в чистом виде, а некоторое его подобие.
Записан
Hooter
Опытный

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

« Ответ #28 : 23-08-2005 05:21 » 

Самый прикол, что в случае работы с Load Library невозможно грузить функции описанные по стандарту С++ только С. Внутре вызывай че хошь а так не моги, так что видимо отменяется вся така байда....

Хотя соблазна велик - хотел бы динамически грузить функции с знанием структур и имен файлов.

Для создания экземпляров классов можно использовать такой механизм, как фабрика. То есть функция,  возвращающая ссылку или указатель на созданный внутри библиотеки класс.

Есть маленький ньюанс во всем этом.
Если я хочу это использовать - то я должен сделать так, что бы создателю DLL не пришлось бы думать как писать. Он должен использовать все просто - создал библиотеку отдал мне - все прогрузилось.

В любом случае, нужен хотя бы минимальный (заранее оговоренный разработчиками) интерфейс взаимодейстия между модулями.

Если будешь использовать фабрику классов, то необходим еще и минимальный интерфейс взаимодействия с экземпляром класса. Можно, по принципу, как это сделано в COM.

Первый модуль.
Код:
class CMyInterface
{
    virtual int some_action () = 0;
}

class CMyClass : public CMyInterface
{
    int some_action ();
    void implementation_func1 ();
    void implementation_func2 ();
}

void * exported createMyClass ()
{
    return new CMyClass;
}

Слово exported использовано для того, чтобы показать, что функция является экспортируемой из модуля.

Второй модуль:
Код:
class CMyInterface
{
    virtual int some_action () = 0;
}

void some_func ()
{
    ...
    createMyClass = ::GetProcAddress (module, "createMyClass");
    ...
    void *instance = createMyClass ();
    CMyInterface *obj = (CMyInterface *)instance;
     int res = obj->some_action ();
}

Здесь интерфейс CMyInterface - является заранее оговоренным интерфейсом взаимодействия с экземпляром класса,
а экспортируемая функция createMyClass - заранее оговоренный интерфейс взаимодействия с модулем (библиотекой).

PS  Гром, я прошу прощения, если это для тебя - прописные истины. Мне просто до сих пор не совсем ясно, как ты себе представляешь себе взаимодействие с чужой библиотекой, если "создателю DLL не пришлось бы думать как писать".
« Последнее редактирование: 23-08-2005 05:37 от Hooter » Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #29 : 23-08-2005 07:25 » 

Я не являюсь супре-гуру, Улыбаюсь поэтому фабрику, например, никогда не использовал.

Я расскажу идею, а вы подумайте.

Звучит примерно так.
Есть идея программы. Не вдаваясь пока (нет у меня еще полного готового описания задачи поэтому не могу поделиться) в саму ее суть, скажу что она технически должна делать....


Имеется ХХХ железо. Оно чего то там делает и имеет коммуникации.

Через некий YYY интерфейс есть возможность тестировать ее готовность после произовдства или в момент разработки.

Пишется программка ААА которая:

а) имеет набор DLL которые закрывают собой наиболее популярные типы интерфейсов (Serial, Network, USB, LPT и т.д.
б) Все они имеют верхний доступный SDK интерфейс, который не связан с типом связи.
г) имеется заранее придуманная структура пакетов, которые будут служить для отправки любых данных внутрь девайса и получаться из него.

Программа умеет создавать и хранить наборы тестов. Умеет их запускать и работать с их результатами.

В качестве тестов иогут быть
а) скрипты
б) DLL

на данный момент выбор типа написания самих тестов до конца не отработан, да и не выбран мной. Можеит а) может б) а скорее всего и то и другое.
Для простых тестов а) для посложнее б).

В варианте б) продуман следующий интерфейс.

1. Инициализирующая фунция.
2. Функции обслуживания теста для реал-тайм или как там пойдет.
3. Функции тестов с набором данных по их вызову (по нескольку типов по желанию заказчика).

Внутри же может быть что угодно....

В SDK вышеупомянутом кроме функций пакетов и функций послки и приема будут функции вызова настроек передачи параметров в программу и т.д. и т.п.


Т.е. структура да обозначена в общих чертах, однако расчет идет на то, что человек который купит такую программу сможет написать DLL как ему хочется только с набором нужных функций и подключить ее
а) в рантайм.
б) без изменения кода программы.
в) сможет получить максимально удобную и простую функциональность для себя.

Теперь моймите меня правильно, что окромя интерфейса внешнего программного есть проблема какой путь подключения выбрать - как его обустроить и вообще....

Пока все находится только в моей голове и проблема с библиотеками возникает именно из-за того, что
а) SDK должны подключаться и в программе и в тестовых билиотеках и иметь общий экземпляр.
б) Я должен уметь правильно все конигурировать из программы для каждого теста - и т.д. и т.п



Записан

А птичку нашу прошу не обижать!!!
Hooter
Опытный

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

« Ответ #30 : 23-08-2005 07:47 » 

что человек который купит такую программу сможет написать DLL как ему хочется только с набором нужных функций и подключить ее
а) в рантайм.
б) без изменения кода программы.
в) сможет получить максимально удобную и простую функциональность для себя.
Что именно будет содержаться в библиотеке, которую напишет пользователь программы? Или что предполагается там содержать? Функции тестов устройств? Или функции для решения каких-то реальных задач? Это разные вещи.

Пока все находится только в моей голове и проблема с библиотеками возникает именно из-за того, что
а) SDK должны подключаться и в программе и в тестовых билиотеках и иметь общий экземпляр.
б) Я должен уметь правильно все конигурировать из программы для каждого теста - и т.д. и т.п
Ну, во-первых, если программа использует и SDK и библиотеки пользователя, то все это происходит в одном процессе и общий экземпляр им должен быть обеспечен.
А во-вторых, такой вопрос: что чем используется? Библиотека пользователя использует SDK или SDK будет использовать библиотеку пользователя?
В-третьих, как я понял основная программа должна обеспечивать эту самую связь? Так?
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #31 : 23-08-2005 09:40 » 

1. содержимое DLL определяется пользователем.
ИМХО - там должны быть тесты, но тестирование может подразумевать наличие трафика в случае тестирование девайса для сети, и содержать некую задачу, которая и будет формировать какие-то ответы, которые обеспечат проверку на ликвидность устройства.

2. Программа пользуется SDK ппользовательские тесты тоже пользуются SDK - это прослойка между нами и интерфейсом устройства.
Я об этом выше писал не раз ....

3. Основная программа обеспечивает визуальную часть и рантайм-запуск всех тестов с установкой пропертис интерфейсво и т.д. и т.д.


Записан

А птичку нашу прошу не обижать!!!
Hooter
Опытный

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

« Ответ #32 : 23-08-2005 10:18 » 

Давай, для простоты примера ограничимся следующим:
1. Основная программа обеспечивает визуальную часть, рантайм загрузку DLL пользователя и рантайм-запуск всех тестов.
2. Инициализация тестов и тестовых случаев проходит в DLL пользователя по инициативе основной программы.
3. Основная программа выводит на экран результаты выполнения функций DLL пользователя.

Пример решения, которое я предлагаю:

1. Рантайм загрузка DLL - никаких сложностей не представляет (это уже обсуждали).

2. Инициализация тестов и тестовых данных - экспортируем из dll пользователя функцию bool init(), которая инициализирует тестовые данные всех тестов в dll пользователя.

3. Запуск всех тестов из dll пользователя основной программой - посмотрим, что для этого нужно... Основной программе нужно знать сколько экспортируется функций из dll пользователя, а также имена этих функций. Пусть dll нам сама об этом скажет - она (или ее разработчик) лучше знает.
Для этого необходимо экспортировать из DLL одну функцию, которая будет возвращать список символьных имен функций тестов. Назовем ее - enumTestFunctions.

4. Возвращение результатов - ограничимся текстовым выводом. Пусть dll делает у себя внутри, что пожелает, а нам пусть предоставит отчет в текстовом виде (const char * или string). Функция в dll, которая это делает, пусть называется getResult.

Итак, что у нас получилось:
1. LoadLibrary (dll пользователя)
2. init = GetProcAddress ("init")
3. init ()
4. enumerateTestFunctions = GetProcAddress ("enumerateTestFunctions")
5. list functions = enumerateTestFunctions ()
6. for each in functions :
6.1. func = GetProcAddress (functions)
6.2. func ()    // <== это запуск очередного теста
7. getResult = GetProcAddress ("getResult")
8. string result = getResult ()
9. show result

Ограничения в этом примере:
1. у функций запуска тестов должна быть одинаковая семантика.
2. минимальный интерфейс библиотеки:
- init
- enumerateTestFunctions
- getResult

Ну как?

Использование SDK библиотек в dll пользователя тоже никакой сложности не представляет.... Так?
« Последнее редактирование: 23-08-2005 10:21 от Hooter » Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #33 : 23-08-2005 19:25 » 

Мля Жаль Я тебе сказад, что не знаю, только одну вещь, которая описана в первом постинге... Улыбаюсь

А вот насчет разработки программного обеспечения я пока не берусь это выносить для всех...

Так что спасибо - но пока я до конца все не продумаю - никак.....

Записан

А птичку нашу прошу не обижать!!!
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #34 : 23-08-2005 20:18 » 

typedef int  (__stdcall *TSetQuery)(void);
.....................
TSetQuery sq1=GetProcAddress(lib1,"SetQuery");
int ins1=sq1();


sq1 = 0000000

Не работает.... Жаль
Записан

А птичку нашу прошу не обижать!!!
Finch
Спокойный
Администратор

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


« Ответ #35 : 23-08-2005 20:57 » 

Тут могут быть несколько ошибок:
1. По каким то причинам библиотека не была найдена. Скорее всего библиотека не была скопирована в каталог запуска EXE файла проекта.
2. Имя функции не было указано коректно. Если в проект не был подключен Def файл, то имя функции в библиотеке будет иметь вид примерно _SetQuery@0

Если что, могу скинуть свои готовые файлы проекта.
« Последнее редактирование: 23-08-2005 21:03 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Hooter
Опытный

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

« Ответ #36 : 24-08-2005 04:01 » 

Мля
Ясно Улыбаюсь Я просто хотел помочь. Извини, ежели чего не так Улыбаюсь
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #37 : 24-08-2005 07:09 » 

Hooter очень зря обиделся - это просто для другой темы.

Цитата
Тут могут быть несколько ошибок:
1. По каким то причинам библиотека не была найдена. Скорее всего библиотека не была скопирована в каталог запуска EXE файла проекта.
2. Имя функции не было указано коректно. Если в проект не был подключен Def файл, то имя функции в библиотеке будет иметь вид примерно _SetQuery@0

Если что, могу скинуть свои готовые файлы проекта.
Меня терзают смутные сомнения....
А с какого момента люди забывают вопрос и начинают обсуждать отвлеченные темы....

1. Причина вообще бредовая, если бы библиотека не была найдена, то ошибка была бы раньше и я не писал бы о невозможности подгрузить функцию, а искал бы причины отсутствия библиотеки - верно?
2. Сколько раз надо писать, что В ПРОЕКТ НЕ БУДУТ ЯВНО ПОДКЛЮЧАТЬСЯ НИКАКИЕ ФАЙЛЫ, потому, что БИБЛИОТЕКА МОЖЕТ И БУДЕТ ПИСАТЬСЯ МНОГО ПОЗДЖЕ ПОДГРУЖАЮЩЕЙ ПРОГРАММЫ ДРУГИМ ЧЕЛОВЕКОМ и ИМЕЯ ТОЛЬКО ФАЙЛ DLL  НАДО УМЕТЬ ПОДГРУЗИТЬ ПРЕДОПРЕДЕЛЕННЫЕ ФУНКЦИИ О КОТОРЫХ В MSDN НАПИСАНО, что __declspec НЕ ДАЕТ В С++ ПОДГРУЖАТЬ ИМЕНА ФУНКЦИЙ....


Мне очень хочется этого добиться - НО НИЧЕГО КРОМЕ ОДНОГО ФАЙЛА В РАНТАЙМ НЕТ. НЕТ ДЕФ ФАЙЛОВ НЕТ НИЧЕГО!!! И ПЕРЕКОМПИЛИРОВАТЬ НЕЛЬЗЯ ....



Все условия выделенные крупным шрифтом многократно описаны в этой теме. Выделение сделано мной.
Записан

А птичку нашу прошу не обижать!!!
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #38 : 24-08-2005 07:13 » 

Убедившись в забывчивости многих по поводу проблемы повторю условия задачи....

1. Есть программа.
2. Есть билиотека.

1 подгружает 2 в процессе работы имея в наличии только файл dll без описательных експортных и т.д. файлов.
Подгрузка должна осуществляться джинамически, без ссылок на возможности компиляции...

Структутра нужных функций и их имена известны

Init
Open
Close
Read
Write
IoCtrl

Положения:

Задача решаема и решена уже в случае:
- dll написана на языке С.
- все вышеуказанные функции находятся под extern C
вся остальная библиотека на С++.

Однако данные решения ограничивают создателя билиотеки технически устаревшими рамками. Это не всегда удобно и добавляет головной боли.

Необходимо найти решение для случая когда ВСЯ библиотека написана на С++ и подключается при вышеуказанных условиях.
Записан

А птичку нашу прошу не обижать!!!
Hooter
Опытный

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

« Ответ #39 : 24-08-2005 07:51 » 

Цитата
Тут могут быть несколько ошибок:
1. По каким то причинам библиотека не была найдена. Скорее всего библиотека не была скопирована в каталог запуска EXE файла проекта.
2. Имя функции не было указано коректно. Если в проект не был подключен Def файл, то имя функции в библиотеке будет иметь вид примерно _SetQuery@0

Если что, могу скинуть свои готовые файлы проекта.
Меня терзают смутные сомнения....
А с какого момента люди забывают вопрос и начинают обсуждать отвлеченные темы....

1. Причина вообще бредовая, если бы библиотека не была найдена, то ошибка была бы раньше и я не писал бы о невозможности подгрузить функцию, а искал бы причины отсутствия библиотеки - верно?
2. Сколько раз надо писать, что В ПРОЕКТ НЕ БУДУТ ЯВНО ПОДКЛЮЧАТЬСЯ НИКАКИЕ ФАЙЛЫ, потому, что БИБЛИОТЕКА МОЖЕТ И БУДЕТ ПИСАТЬСЯ МНОГО ПОЗДЖЕ ПОДГРУЖАЮЩЕЙ ПРОГРАММЫ ДРУГИМ ЧЕЛОВЕКОМ и ИМЕЯ ТОЛЬКО ФАЙЛ DLL  НАДО УМЕТЬ ПОДГРУЗИТЬ ПРЕДОПРЕДЕЛЕННЫЕ ФУНКЦИИ О КОТОРЫХ В MSDN НАПИСАНО, что __declspec НЕ ДАЕТ В С++ ПОДГРУЖАТЬ ИМЕНА ФУНКЦИЙ....
[/b]
Гром, для использования функции GetProcAddress не нужно подключать DEF файл к приложению, в котором ты хочешь использовать DLL.

DEF файл нужно подключить к тому проекту, в котором ты (или пользователь твоей системы) создаешь библиотеку. Просто необходимо, чтобы нужная тебе функция была прописана в таблице импорта библиотеки.

Теперь, если у тебя есть DLL, с корректной таблицей импорта, то для ее использования в твоем приложении тебе нужно иметь только DLL файл. И вызвать LoadModule - GetProcAddres...

Вот цитата из msdn по этому поводу:

"You can only obtain the export ordinal if the DLL you are linking to was built with a module definition (.DEF) file, and if the ordinals are listed with the functions in the EXPORTS section of the DLL's .DEF file."


Теперь о __declspec.

Использовние этой директивы не позволяет подгружать библиотеки динамически, тем более не зная заранее ее содержимого. ДЛя подключения таких библиотек необходимо иметь lib- и h-файлы.
Пусть меня поправят, если в чем-то ошибся.



Убедившись в забывчивости многих по поводу проблемы повторю условия задачи....

1. Есть программа.
2. Есть билиотека.

1 подгружает 2 в процессе работы имея в наличии только файл dll без описательных експортных и т.д. файлов.
Подгрузка должна осуществляться джинамически, без ссылок на возможности компиляции...

Структутра нужных функций и их имена известны

Init
Open
Close
Read
Write
IoCtrl

Положения:

Задача решаема и решена уже в случае:
- dll написана на языке С.
- все вышеуказанные функции находятся под extern C
вся остальная библиотека на С++.

Гром, может ты сразу напишешь, что и каким образом уже сделано, чтобы никто не задавал повторяющихся вопросов?..
А то с каждым твоим ответом выясняется все больше и больше...

Что это за функции, например? Названия похожи на функции библиотеки драйвера устройства...
Эти функции предполагается экспортировать из библиотеки пользователя или это какие-то внутренние функции используемые приложением?

Ты так и не ответил на вопрос: какое место занимает SDK во взаимодействии модулей?
Мне видится следующее: SDK само по себе знает только об устройствах и интерфейсах с ними; библиотека пользователя использует SDK; приложение использует библиотеку пользователя и, может быть, SDK. Так? Или по-другому? Напиши как..
« Последнее редактирование: 20-12-2007 14:53 от Алексей1153++ » Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #40 : 24-08-2005 09:00 » 

 Быть такого не может не верю - что все что я написал вызывает след. вопросы...

Цитата
Гром, для использования функции GetProcAddress не нужно подключать DEF файл к приложению, в котором ты хочешь использовать DLL.
Финч предлагал сделать именно с деф файлом. Я так и сказал, где ты увидел, что я это пишу?

Цитата
Теперь, если у тебя есть DLL, с корректной таблицей импорта, то для ее использования в твоем приложении тебе нужно иметь только DLL файл. И вызвать LoadModule - GetProcAddres...

Опять вернемся к вопросу о том, что ТАКИМ ОБРАЩОМ ТЫ НЕ СМОЖЕШЬ ПОДКЛЮЧИТЬ ФУНКЦИИ ОПИСАННЫЕ И СОБРАННЫЕ В С++ стандарте. Перечитай задание еще раз.


Цитата
Использовние этой директивы не позволяет подгружать библиотеки динамически, тем более не зная заранее ее содержимого. ДЛя подключения таких библиотек необходимо иметь lib- и h-файлы.
Пусть меня поправят, если в чем-то ошибся.
Где я это писал??? Этот макрос нужен для указания билиотеке что она эту функцию экспортирует... Причем тут загрузка?

По деф-файлу...

Я понимаю, что он необходим билиотеке, но насколько я понимаю, это информационный файл создаваемый ДЛЯ МЕНЯ, как для подгружающего члена - устаревший способ подгрузить билиотеку. Вытащить имена.
А динамическое подключение - это когда у меня есть только ДЛЛ файл и я на ДРУГОЙ машине где НЕТ ДЕФ-файла подключаю ДЛЛ в программу - какая связь со всем вышесказанным???


Цитата
Гром, может ты сразу напишешь, что и каким образом уже сделано, чтобы никто не задавал повторяющихся вопросов?..
А то с каждым твоим ответом выясняется все больше и больше...

Выше написанная тобой цитата содержит все что сделано. То что все делается через динамическую подгрузку в теме написано 50 раз - вопрос совершенно бессмысленен при нормальном чтении темы.

Цитата
Что это за функции, например? Названия похожи на функции библиотеки драйвера устройства...
Эти функции предполагается экспортировать из библиотеки пользователя или это какие-то внутренние функции используемые приложением?

Ты когда тебе дают на работе написать интерфейс, то же интересуешься кому чего надо и пока не пояснят - не работаешь...Не понял

Я не буду ничего пояснять - задача сформулирована, ответ желательно найти, только те кто хочет - пишет, кто просто так ради вопросов - лучше не надо.
Записан

А птичку нашу прошу не обижать!!!
npak
Команда клуба

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

« Ответ #41 : 24-08-2005 09:01 » 

Разработчик библиотеки "2" отдаёт разработчику приложения 1 три артефакта:
  заголовочный файл
  библиотеку импортов (.lib)
  реализацию функций в DLL

Пара "заголовки" + "загрузочные библиотеки (.lib)" и есть SDK в его обычном понимании, необходимы для компиляции приложения 1.  DLL представляет собой Runtime и нужна для запуска приложения и отладки

Заголовочные файлы необходимы для того, чтобы разработчик приложения 1 знал, какие функции предоставляет библиотека 2, какие параметры принимают функции и что возвращают.  DLL предоставляет реализацию функций.  Библиотека импортов освобождает разработчика приложения 1 от мудоханья с LoadLibrary и GetProcAddress.  При запуске приложения в ходе инициализации код, содержащийся в библиотеке импортов, загрузит нужную DLL или выдаст сообщение, что DLL не найдена и приложение завершится -- стандартная обёртка для LoadLibrary.

В коде приложения 1 стоит просто вызов функции Init.  Этот вызов реализован в библиотеке импортов и сделает следующее: возьмёт указатель соответствующей функции из DLL и вызовет её.  При этом для разработчика приложения 1 не важно, на каком языке написан код и какие на самом деле имена функций в DLL -- эта информация зашита в библиотеку импортов при компиляции.

Теперь как разработчик библиотеки 2 сделает искомые артефакты.  Понятно, что заголовочный файл он напишет ручками, DLL получится компиляцией исходников библиотеки.  Единственный немного нетривиальный шаг -- откуда возьмётся библиотека импортов.  Для того, чтобы её получить, надо сообщить компилятору, какие функции библиотеки предназначены для внешнего использования.  Это можно сделать двумя способами.  Способ первый -- написать .def файл и перечислить в нём те функции, которые библиотека экспортирует, и включить этот файл в проект библиотеки.  Подчёркиваю, библиотеки, а не приложения.  Приложению он нафиг не нужен, у приложения есть библиотека импортов.  При компиляции библиотеки вижуал студия найдёт .def файл и сгенерирует по нему библиотеку загрузки.  Способ второй, пометить в исходниках библиотеки экспортируемые функции при помощи декларатора  __declspec( dllexopt ).  Компилятор автоматически включит код для вызова экспортируемых функций в библиотеку импортов.

Вот, собственно, и вся схема.  Ей пользуется немеряно народу по всему миру.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Hooter
Опытный

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

« Ответ #42 : 24-08-2005 09:31 » 

Гром, я тебя сразу попрошу дочитать до конца и только потом отвечать.

Цитата
Теперь, если у тебя есть DLL, с корректной таблицей импорта, то для ее использования в твоем приложении тебе нужно иметь только DLL файл. И вызвать LoadModule - GetProcAddres...

Опять вернемся к вопросу о том, что ТАКИМ ОБРАЩОМ ТЫ НЕ СМОЖЕШЬ ПОДКЛЮЧИТЬ ФУНКЦИИ ОПИСАННЫЕ И СОБРАННЫЕ В С++ стандарте. Перечитай задание еще раз.

Я и не говорил, что сможешь. Я и Finch попытались тебе объяснить, почему у тебя возникла ошибка при вызове GetProcAddress.


Цитата
Использовние этой директивы не позволяет подгружать библиотеки динамически, тем более не зная заранее ее содержимого. ДЛя подключения таких библиотек необходимо иметь lib- и h-файлы.
Пусть меня поправят, если в чем-то ошибся.
Где я это писал??? Этот макрос нужен для указания билиотеке что она эту функцию экспортирует... Причем тут загрузка?

При том, что ты хочешь подгружать библиотеки динамически. Так? Но подгрузить библиотеку динамически, которая экспортирует код через __declspec, нельзя. И тем более нельзя подключить код С++.


По деф-файлу...
Я понимаю, что он необходим билиотеке, но насколько я понимаю, это информационный файл создаваемый ДЛЯ МЕНЯ, как для подгружающего члена - устаревший способ подгрузить билиотеку. Вытащить имена.
А динамическое подключение - это когда у меня есть только ДЛЛ файл и я на ДРУГОЙ машине где НЕТ ДЕФ-файла подключаю ДЛЛ в программу - какая связь со всем вышесказанным???

Давай еще раз попробую объяснить.
Для тебя, как для подгружающего члена не нужен DEF  файл. На какой машине бы ты не был. На другой или на своей. Для динамической загрузки достаточно только DLL.
Я уже писал об этом.

Цитата
Гром, может ты сразу напишешь, что и каким образом уже сделано, чтобы никто не задавал повторяющихся вопросов?..
А то с каждым твоим ответом выясняется все больше и больше...

Выше написанная тобой цитата содержит все что сделано. То что все делается через динамическую подгрузку в теме написано 50 раз - вопрос совершенно бессмысленен при нормальном чтении темы.

К сожалению, при нормальном чтении темы не создается полной картины твоей задачи. Поэтому я предлагаю тебе (если ты ожидаешь, что тебе помогут) обрисовать сразу всю картину и не добавлять по одному условию с каждым своим постом.

Вот это, например, всплыло только сегодня:

Задача решаема и решена уже в случае:
- dll написана на языке С.
- все вышеуказанные функции находятся под extern C
вся остальная библиотека на С++.


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

Даже как-то странно слышать. Как можно решить задачу правильно, не зная всех ограничений. Или ты хочешь получить множество всех возможных решений во вселенной, а из них уже выбрать?
Проще описать ограничения, чем все возможные решения Улыбаюсь
Только не надо здесь писать, что уже описал все ограничения.
Мне просто показалось, что наличие функций Init, Write, Ioctl, ... может повлиять на конечное решение.

А вот на этот вопрос ты вообще толком ни разу не ответил. В основном какими-то обрывками фраз.

Ты так и не ответил на вопрос: какое место занимает SDK во взаимодействии модулей?
Мне видится следующее: SDK само по себе знает только об устройствах и интерфейсах с ними; библиотека пользователя использует SDK; приложение использует библиотеку пользователя и, может быть, SDK. Так? Или по-другому? Напиши как..
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #43 : 24-08-2005 09:33 » 

отвечать не буду...
По h & lib файлам сказано столько что умереть можно...
Программист пишущий библиотеку НИЧЕГО ЕН МОЖЕТ ПРЕДОСТАВИТЬ АВТОРУ ПРОГРАММЫ, потому что он эту программу купил в бинарнике , а бинарнику нах не нужны вышеупомянутые файлы.
Записан

А птичку нашу прошу не обижать!!!
Hooter
Опытный

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

« Ответ #44 : 24-08-2005 09:34 » 

Разработчик библиотеки "2" отдаёт разработчику приложения 1 три артефакта:
 заголовочный файл
 библиотеку импортов (.lib)
 реализацию функций в DLL
...
Вот, собственно, и вся схема. Ей пользуется немеряно народу по всему миру.

npak, респект
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #45 : 24-08-2005 09:44 » 

предыдущий ответ Нпаку.

Хутер....
Цитата
Я и не говорил, что сможешь. Я и Finch попытались тебе объяснить, почему у тебя возникла ошибка при вызове GetProcAddress.
вы вообще поняли чего сказали тогда???


Эта ошибка с невозможностью подгрузки вознимкает потому, что в стандарте Майкрософт С++ имя функции трансформируется с Init  ---> __Init_hjsk123lksj243k23j43....

И ни по какой другой причине это не происходит.....

Цитата
К сожалению, при нормальном чтении темы не создается полной картины твоей задачи. Поэтому я предлагаю тебе (если ты ожидаешь, что тебе помогут) обрисовать сразу всю картину и не добавлять по одному условию с каждым своим постом.


Даже как-то странно слышать. Как можно решить задачу правильно, не зная всех ограничений. Или ты хочешь получить множество всех возможных решений во вселенной, а из них уже выбрать?

Все очень просто - есть пост

Цитата
1. Есть программа.
2. Есть билиотека.

1 подгружает 2 в процессе работы имея в наличии только файл dll без описательных експортных и т.д. файлов.
Подгрузка должна осуществляться джинамически, без ссылок на возможности компиляции...

Структутра нужных функций и их имена известны

Init
Open
Close
Read
Write
IoCtrl

Положения:

Задача решаема и решена уже в случае:
- dll написана на языке С.
- все вышеуказанные функции находятся под extern C
вся остальная библиотека на С++.
Это условие задачи.
Если ты ее решить не можешь - не решай. В условии сказано достаточно - что бы решить проблему.
Это же было написано в постинге....
Цитата
Самый прикол, что в случае работы с Load Library невозможно грузить функции описанные по стандарту С++ только С. Внутре вызывай че хошь а так не моги, так что видимо отменяется вся така байда....

То бишь надо просто читать все внимательно - а не по диагонали....

Поначалу я спрашивал одно. Будет ли при вызове одной библиотеки из другой библиотеки и в программе - экземпляр единым. Вышло что будет - поверил, хоть и не проверял пока.

Потом вопрос стал - как с помощью  LoadLibrary подгрудать функции в стандарте С++.

Теперь высняется, что мало кто реально понял чего спрашивают, более того - несмотря на глубочайшие познания в С++ никто не понял почему же они не подключаются.

LoadLibrary не пользуется h , lib & def файлами, но мне в каждом втором постинге пытаются рассказать как удобно ими пользоваться.

Написано не раз, что программа в бинарнике должна уметь работать с новыми билиотеками без возможностей пересборки, нпак в пердыдущем посте пишет простынку о преимуществах знания формата экспорта с помощью этих файлов разработчику программы....

Впопрос - зачем эти постинги мне? Зачем последний пост с вопросом об истином смысле задачи.

Я хочу получить не бублиотеку не ее структуру, а метод вызова функции одной с помощью двух процедур из юилиотеки написанной НА С++ а мне опять спрашивают зачем - мне надо....


Ну и напоследок маленький практический совет.

Учитесь писать интерфейсы по описанию задачи.
Есть абстракция и ее надо формализовать.
И не спрашивайте зачем и кому эта абстракция нужна.

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


Записан

А птичку нашу прошу не обижать!!!
Hooter
Опытный

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

« Ответ #46 : 24-08-2005 09:48 » 

Эта ошибка с невозможностью подгрузки вознимкает потому, что в стандарте Майкрософт С++ имя функции трансформируется с Init ---> __Init_hjsk123lksj243k23j43....

И ни по какой другой причине это не происходит.....
Улыбаюсь Я вижу, что мы говорим о разных вещах, но пытаюсь тебе объяснить - трансформация имени происходит из-за того, что при создании библиотеки ты не указал DEF файл. А для использования этой библиотеки DEF файл не нужен.
« Последнее редактирование: 24-08-2005 09:52 от Hooter » Записан
Hooter
Опытный

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

« Ответ #47 : 24-08-2005 09:53 » 

Я решил делать маленькие посты, чтобы было легче читать.

Давай так.
Тебе нужно динамически поключать библиотеку.
Вот шаги для этого (я знаю, что ты знаешь, но это просто для уточнения):
1. LoadLibrary
2. GetProcAddress + вызов по полученному адресу.
3. FreeLibrary

Использовать код С++ с помощью динамического подключения нельзя.

Использовать библиотеку ничего не зная о ее содержимом - невозсможно
Записан
Hooter
Опытный

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

« Ответ #48 : 24-08-2005 09:59 » 

Третий мой пост. Гром, не пропускай два предыдущих.

Поначалу я спрашивал одно. Будет ли ....
...
Потом вопрос стал - как с помощью  ...

То то и оно. Народ тебе почти сразу сказал, что сделать, как ты хочешь, нельзя. Именно поэтому люди тебе предлагали другие варианты решения твоей проблемы.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #49 : 24-08-2005 11:05 » 

По постингам
1. Деф файл никак не влияет на образование имен в ДЛЛ. Он влияет на факт линковки ДЛЛ в основной процесс. Если Деф файл есть, то при подключении на стадии линковки можно вместо хедер и либ файлов использовать Деф файл где имена функций можно переопределить.

При собирании в Майкрософт студии любой стандартной созданной визардом библиотеки Деф файл создается самостоятельно.


2. Использовать и подгружать файлы можно. Я уже эту проблему решил, теперь осталось узнать есть ли у вас желание решить задачу или есть желание только поспорить....

3. Ни одного варианта решения второй проблемы предложено не было и не предложено до сих пор.
За первую спасибо, ибо мне нужно было именно эксперементальное подтверждение теории, которое вы мне предоставили. И обосновали.
Записан

А птичку нашу прошу не обижать!!!
npak
Команда клуба

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

« Ответ #50 : 24-08-2005 11:07 » 

Сорри, я как-то решил, что DLL будет использоваться приложением, которое только разрабатывается.  А приложение то, оказывается, уже готово, надо написать к нему плугин, которое приложение по своим собственным правилам подцепит. Понимание верное?

Приложение 1 уже есть, надо сделать DLL 2, затем как-то подпихнуть её приложению 1.

Если приложение 1 уже готово, то должно быть описано, что и как оно грузит.  Предположим, что для того, чтобы DLL могла использоваться приложением, надо, чтобы оно предоставляло функции

Init
Open
Close
Read
Write
IoCtrl

Если это так, то достаточно реализовать в DLL указанные функции так, чтобы в результате они получили именно такие имена.
на Си++, очевидно, это выглядит так
extern "C" WINAPI __declspec( dllexport) return_type Init(input_type_1 arg1, /* аргументы */ )

аналогично остальные функции из интерфейса библиотеки.

Насчёт WINAPI я погорячился, это зависит от приложения, что ему надо.  Некоторым нужны WINAPI (__stdcall), нектором __cdecl.  Должно быть описано в доках по написанию плугинов к приложению. 

В таком сценарии использования устройство библиотеки подчиняются правилам, которые задёт приложение.

« Последнее редактирование: 24-08-2005 11:29 от npak » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
npak
Команда клуба

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

« Ответ #51 : 24-08-2005 11:37 » 

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

Если такая постановка задачи верна, то по-хорошему, приложение должно предоставлять Extension API -- определённый набор функций, которые может вызывать плугин.  Если такого API нет, то ответ зависит от устройства приложения, его библиотек и операций, которыми хочет воспользоваться плугин.   Так навскидку сказать общий рецепт ... затруднительно.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #52 : 24-08-2005 11:51 » 

npak - умничка, я два дня доходил до WINAPI  там стдколы вроде как не нужны в данном случае.

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

А птичку нашу прошу не обижать!!!
Finch
Спокойный
Администратор

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


« Ответ #53 : 24-08-2005 11:57 » 

Гром, За этот топик ты меня отдергиваеш уже третий раз. Я дал тебе рабочий пример, который я проверил в VC++6.0. Определись что тебе нужно.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
npak
Команда клуба

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

« Ответ #54 : 24-08-2005 12:22 » 

npak - умничка, я два дня доходил до WINAPI  там стдколы вроде как не нужны в данном случае.

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

Спасибо за добрые слова Улыбаюсь но ...

Если для обычной функции Си++ задать WINAPI, то это не спасёт от переименования.

Например, в исходниках задано
Код:
int __declspec( dllexport ) WINAPI  Init()

В DLL получим функцию с именем ?Init@@YGHXZ

Надо заставлять разработчиков плугина писать extern "C"

Альтернативой является чтобы плугин при инциализации сам сообщал приложению адреса своих функций.  Так, например, поступает виртуальная машина Java -- тот, кто хочет ей пользоваться, должен передать структуру с 25 функциональными указателями, для каждого из которых задана семантика.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #55 : 24-08-2005 12:44 » 

Я полностью не проверял, но в принципе так и делается сейчас, будет именнно так - что пользователь должен будет заполнять в своей функции типа Init все остальные поля...

Но почему ты считаешь что будет переименование, насколько мне известно - нет не будет...


Финч - где ты писал, что надо сделать WINAPI ?
Если писал - то извини, видимо и я плохо читал.
Записан

А птичку нашу прошу не обижать!!!
Finch
Спокойный
Администратор

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


« Ответ #56 : 24-08-2005 12:55 » 

Файл WinDef.h
Код:
#define CALLBACK    __stdcall
#define WINAPI      __stdcall
#define WINAPIV     __cdecl
#define APIENTRY    WINAPI
#define APIPRIVATE  __stdcall
#define PASCAL      __stdcall
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
npak
Команда клуба

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

« Ответ #57 : 24-08-2005 13:11 » 

Но почему ты считаешь что будет переименование, насколько мне известно - нет не будет...

Я проверил.  Собрал DLL с  функцией, написанной на Си++, и посмотрел на имя в таблице экспортов получившейся DLL (эта та самая таблица, которой пользуется GetProcAddress чтобы сконвертировать строковое имя функции в адрес).  Посмотрел при помощи утилиты dumpbin

Оказалось, что у в таблице только одна запись, и эта запись имеет вид ?Init@@YGHXZ.  На С++ декларацию "int WINAPI Init(void)" это походит только отадалённо.
« Последнее редактирование: 24-08-2005 13:14 от npak » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Finch
Спокойный
Администратор

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


« Ответ #58 : 24-08-2005 13:26 » 

Чтобы исключить дальнейшие споры, собственно RTFM Дж. Рихтер "Виндовс -для проффессионалов" Глава 19.
Цитата
С инструментальные средства от разных поставщиков создают проблемы Дело в том, что компилятор Microsoft С, экспортируя С-функцию, искажает eе имя, даже если Вы вообще не пользуетесь С++ Это происходит, только когда Ваша функция экспортируется по соглашению __stdcall. (Увы, это самое популярное соглашение ) Тогда компилятор Microsoft искажает имя С-функции. впереди ставит знак подчеркивания, а к концу добавляет суффикс, состоящий из символа @ и числа байтов, передаваемых функции в качестве параметров. Например, следующая функция экспортируется в таблицу экспорта DLL как _MyFunc@8:


__declspec(dllexport) LONG __stdcall MyFunc(int a, int b);

Если Вы решите создать ЕХЕ-файл с помощью средств разработки от другого поставщика, то компоновщик попытается скомпоновать функцию MyFunc, которой нет в файле DLL, созданном компилятором Microsoft, и, естественно, произойдет ошибка

Чтобы средствами Microsoft собрать DLL, способную работать с инструментарием от другого поставщика, нужно указать компилятору Microsoft экспортировать имя функции бсз искажений. Сделать это можно двумя способами Первый — создать DEFфайл для Вашего проекта и включить в него раздел EXPORTS так:


EXPORTS MyFunc


Компоновщик от Microsoft, анализируя этот DEF-файл, увидит, что экспортировать надо обе функции: __MyFunc@8 и MyFttnc. Поскольку их имена идентичны (не считая вышеописанных искажений), компоновщик на основе информации из DEF-файла экспортирует только функцию с именем MyFunc, а функцию _MуFипс@8 не экспортирует вообще.

Может, Вы подумали, что при сборке ЕХЕ-файла с тикой DLL компоновщик от Microsoft, ожидая имя _MyFunc8, не найдет Вашу функцию? В таком случае Вам будет приятно узнать, что компоновщик все сделает правильно и корректно скомпонует ЕХЕ-файл с функцией MyFunc.

Если Вам не по душе DEF-фаЙлы, можете экспортировать неискаженное имя функции еще одним способом. Добавьте в один из файлов исходного кода DLL такую строку:


#pragma comment(linker, "/export:MyFunc=_MyFunc@8")


Тогда компилятор потребует от компоновщика экспортировать функцию MyFunc с той же точкой входа, что и _MyFunc@8. Этот способ менее удобен, чем первый, так как здесь приходится самостоятельно вставлять дополнительную директиву с искаженным именем функции И еще один минус этого способа в том, что из DLL экспортируется два идентификатора одной и той же функции MyFunc и _МуFипс@8, тогда как при первом способе — только идентификатор MyFunc. По сути, второй способ не имеет особых преимуществ перед первым — он просто избавляет от DEF-файла

Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #59 : 24-08-2005 13:32 » 

Finch
Спасибо, но это очень и очень плохо....
Мне надо сделать так, что бы разработчик библиотеки не замарорачивался всей этой лабудой, а делал бы так как ему надо - с маленькими упрощениями...

Увы плохо все это....
Записан

А птичку нашу прошу не обижать!!!
npak
Команда клуба

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

« Ответ #60 : 24-08-2005 13:54 » 

Тогда пусть разработчик библиотеки напишет одну функцию инициализации как extern "C" а остальные передаст как указатели в структуре.  ИМХО, довольно гибкая схема, поддерживает расширяемость, не предъявляет больших требований к совместимости компиляторов, которыми собраны приложение и dll
опять-таки множество народу ей пользуется.
Код:
 typedef struct _ServiceProvider_01 {
    int ApiVersion;
    OpenFunction Open;
    CloseFunction Close;
    ReadFunction Read;
    WriteFunction Write;
    IoCtrlFunction IoCtrl;
} ServiceProvider;
   
extern "C" int  __cdecl  Init(int minVersion, ServiceProvider ** pp_provider);

Поле ApiVersion позволит расширять возможности приложения и библиотек и сохранять при этом обратную совместимость.  Аргумент minVersion позволит приложению указать минимальную версию API которую библиотека должна предоставить приложению.  В pp_provider библиотека передаёт указатель на массив реализованных функций.

Если приложение предоставляет функции библиотеке (Extension API), то может делать это в той же самой манере -- через структуру с номером версии и массивом функций.  Указатель на структуру передавать функции Init при загрузке DLL
« Последнее редактирование: 24-08-2005 13:58 от npak » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Alf
Гость
« Ответ #61 : 24-08-2005 14:14 » 

Тогда компилятор Microsoft искажает имя С-функции. впереди ставит знак подчеркивания, а к концу добавляет суффикс, состоящий из символа @ и числа байтов, передаваемых функции в качестве параметров.

Рихтер не оговаривает, о каком именно компиляторе идет речь? И применимы ли эти данные только к C или и к C++ тоже? Например, в моем случае функция

Код:
void MDString(char *str, unsigned char *d);

в DLL превращается в

Код:
?MDString@@YAXPADPAE@Z

(компилятор VC++ из состава VS.NET 2003).
Записан
npak
Команда клуба

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

« Ответ #62 : 24-08-2005 14:23 » 

Код:
void MDString(char *str, unsigned char *d);

в DLL превращается в

Код:
?MDString@@YAXPADPAE@Z

(компилятор VC++ из состава VS.NET 2003).

Данный пример характерен только для Си++ (name mangling)
То, о чём пишет Рихтер, справедливо только для компилятора Си (без плюсов), проверено на VC 6.0 и VC 7 (.NET 2003)

Код:
int __declspec( dllexport ) WINAPI myFunc_WINAPI(int x, int y) { return x + y; }

int __declspec( dllexport ) __cdecl myFunc_cdecl(int x, int y) { return x + y; }

Даёт _myFunc_WINAPI@8 и  myFunc_cdecl соответственно.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Finch
Спокойный
Администратор

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


« Ответ #63 : 24-08-2005 18:38 » 

Гром, у меня такой вопрос. Когда ты пишеш драйвера, Майкрософт волнует твои проблемы, что ты хочеш намного проше. Она тебе дала DDK. Сказала, что драйвер должен иметь определенную структуру и должен почти незамедлительно отвечать на определенные запросы и все. Майкрософт не волнует, что ты будеш творить внутри драйвера, это твои проблемы. Самое главное соблюдай внешний интерфейс. Также и здесь. Сделай шаблон .h файла. Заведи туду все функции интерфейса библиотеки. Задокументируй их и все. Как разработчик библиотеки будет реализовывать внутри, тебя не должно волновать, это его проблемы. Самое главное, чтобы интерфейсные функции отрабатывались однозначно согласно документации.
« Последнее редактирование: 24-08-2005 18:42 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #64 : 24-08-2005 18:39 » 

Finch тут вот какое дело...
Я ведь не майкрософт....
Записан

А птичку нашу прошу не обижать!!!
Finch
Спокойный
Администратор

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


« Ответ #65 : 24-08-2005 18:45 » 

Гром, а разве разработчиков Far или WinAMP волновало проблемы стороних разработчиков. Они сделали четкий интерфейс плугина и все. Сказали, если хотите строить свои дополнения, делайте это по таким правилам. Иначе не будет работать.
Полиморфизм интерфейса при всей его привлекательности вызовет только больше головных болей у разработчиков. Так как ловля блох, когда не известно кто глючит, не самое привлекательное занятие. И нет строго определенных правил, значит будут разночтения. Да и основной модуль будет на порядки сложнее.
« Последнее редактирование: 24-08-2005 21:05 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Chaa
Помогающий

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

« Ответ #66 : 25-08-2005 06:54 » 

Если не хочется ограничивать пользователя программы в средствах, то лучше, на мой взгляд, использовать COM. Тогда библиотеки можно будет на Delphi писать, на Visual Basic, или даже на JavaScript.

А если хочется сделать для пользователей проще, то лучше сделать шаблон библиотеки на Си, с уже написанными прототипами функций, с файлами проекта, так, чтобы пользователь мог писать только код работы с устройством, не задумываясь о том, как библиотека подключится к основной программе.
Записан
Hooter
Опытный

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

« Ответ #67 : 25-08-2005 07:15 » 

Гром, если не секрет, почему такое трепетное отношение к пользователям уже готовой программы?
Пусть пишут как хотят, а потом сделают врапперы для существующего интерфейса.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #68 : 25-08-2005 07:41 » 

Ну - давайте по порядку..

Chaa  - DLL  то же можно писать на любом языке - просто не использовать заголовки от С++. Улыбаюсь СОМ для этого без надобности...

Написание плагина на С++ на порядок проще чем написание его на СОМ для ИЕ.
Попробуй на РСДН почитать статьи (единственные кстати) по написанию плагина к ксплореру - мрак.

Да и не работает ничего....



Теперь о нежном отношении Улыбаюсь

Скажу прямо. Как вы сами смотрите - много ли сайтов начинавшихся с наколенной  сборки в виде страничке на фри хостинге прорывается на уровень 1000 и более посетителей в день и живет более 2-х месяцев?

Думаю, что все вы ответите - нет очень мало.

Думаю, что талант по раскрутке сайтов, и вообще по созданию потребного контента у меня есть.... Улыбаюсь пример - этот форум, на которым все вы обитаете Улыбаюсь хотя бы периодически.
Это без ложной скромности хороший (не отличный) результат....

Дабы было понятно, я был в свое время частным предпринимателем и примерно понимаю как происходят продажи. Улыбаюсь Примерно - это мои 2-3 года в роли менеджера продаца и хозяина в одном лице с оборотом в городе до 400000 жителей в 10 000 бакосви доходом в 1000 - 1500 в месяц. Согласитесь - результат неплохой - если учесть что начиналось все с пустого места и комнате в студ. общаге....

Вывод - я немного понимаю в системе продаж вообще и в маркетинге в частности....

Далее, я работаю в западных системах софтвеного производства уже более 7 лет. Это говорит о факте моего близкого знакомства как к раздолбайскому процессу производства, так и о знакомстве с основными правилами местных продаж софта.

Проблема звучит так.

Майкрософт - как единственный крупный производитель самой распространенной системы в мире может позволить себе не думать о конечном пользователе.
Он заботится о гигантах клиентах - таких как АОЛ Боинг, и т.п.

Винамп  - не показатель, так как он бесплатен. Его плагины никак не влияют на процесс воспроизведения музыки - есть функциональность от плагинов независящая.



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

Идея сама по себе тривиальна, но ее нет в реализации, а спрос на нее есть и не маленький.


Поэтому основой моих изысканий в начале пути стоит след процесс. Я разрабатываю систему, которая должна жить годы.
Мне должно быть удобно и легко ее модифицировать и улучшать.
Пользователи не должны зависить от моей работоспособности и им тоже должно быть удобно.
Тогда и продажи будут выше и популярность....

Записан

А птичку нашу прошу не обижать!!!
Chaa
Помогающий

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

« Ответ #69 : 25-08-2005 07:57 » 

Лично я, как пользователь, предпочел бы, чтобы с программой поставлялись готовые исходники одной из библиотек (м.б. самой простой). Чтобы открыв ее в Visual Studio я мог посмотреть код внутри функций Open/Close/Read/Write/IoCtrl и убрав его написать свой. Или изменить существующий под свои нужды.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #70 : 25-08-2005 08:33 » 

Chaa - это само собой - простейший пример в виде исходников и бинарника будет в девелопмент пакете с лицензией.

Записан

А птичку нашу прошу не обижать!!!
Hooter
Опытный

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

« Ответ #71 : 25-08-2005 08:34 » 

Поэтому основой моих изысканий в начале пути стоит след процесс. Я разрабатываю систему, которая должна жить годы.
...
Пользователи не должны зависить от моей работоспособности и им тоже должно быть удобно.

Почему же ты тогда настаиваешь на использовании С++?
Сам ведь сказал: можно использовать любой язык для создания DLL...
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #72 : 25-08-2005 08:58 » 

С++ базовый язык сегодняшнего дня.
Это раз.

При работе с тестами оборудовения никто не использует другого, ибо неудобно
Это два.

Однако при желании можно создавать нужные билиотеки на любом языке
Это три

Улыбаюсь
Записан

А птичку нашу прошу не обижать!!!
Hooter
Опытный

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

« Ответ #73 : 25-08-2005 10:20 » 

Если тебе не трудно, расскажи, плз, по какому пути ты решил развивать свое приложение дальше, когда определишься. Думаю, не мне одному будет интересно.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #74 : 25-08-2005 12:34 » 

По пути одной функции extern "C"
Записан

А птичку нашу прошу не обижать!!!
Finch
Спокойный
Администратор

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


« Ответ #75 : 25-08-2005 12:35 » 

В свое время я эксперементировал с такой схемой построения приложений. Сушествует ядро программы. Его дело только функции диспетчера. Для других модулей он является отправителем и получателем сообшений. Все остальные модули оформлены в виде библиотек и несут основную смысловую нагрузку программы. Функциональность программы будет целиком и полностью зависить от подключенных модулей к ней. Все модули изолированы друг от друга, обшаются только через ядро программы. Модули предоставляют сервисы. Которые будут зарегистрированы в ядре. Если модулю нужно какое либо действие или информация с другого сервиса, он посылает запрос ядру с номером того сервиса. Ядро транслирует запрос дальше и затем возрашает ответ сервису отправителю.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #76 : 25-08-2005 13:06 » 

Finch - это не совем то, что ты пишешь.
Ядро - да - экспортируемые модули, да, но основа - трансляция результатов, запуск приложений и многое другое Улыбаюсь
Записан

А птичку нашу прошу не обижать!!!
Chaa
Помогающий

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

« Ответ #77 : 26-08-2005 04:21 » 

Все таки к C++ намного ближе COM, чем передача через одну функцию множества указателей.
Если использовать ATL, то написание и использование COM-объектов будет достаточно простым. Практически каркас COM-объекта полностью может создаваться с помощью визардов студии.
Кстати я писал и расширения к эксплореру и плагин к интернет эксплореру. Это только сначала кажется, что там все очень сложно. Нужно просто немного привыкнуть. Основная сложность там - это неполная документация. Но здесь все в твоих руках.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #78 : 26-08-2005 06:53 » 

Для того, что бы нрписать DLL достаточно легкого движения кисти...

СОМ понимают далеко не все.

Так как будет и продолжение, то СОМ рассматривается как след. этап дабы создавать сервера тестовых СОМ...

Но это потом. Сначала концепт.
Записан

А птичку нашу прошу не обижать!!!
npak
Команда клуба

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

« Ответ #79 : 26-08-2005 09:36 » 

Признаться, одним из первых порывов было предложить перевести архитектуру на COM

Но потом нашёл, что у СОМ проблем будет не меньше, а может даже и больше, чем бонусов.

Во-первых, нужно прописывать компоненты в реестре, что усложняет deployment (развёртывание) плагина
Во-вторых, если DLL предоставляет только один инстанс объекта с заданным интерфейсом (Open Close Read Write IoCtrl), то объектная модель тут ни к чему

На мой взгляд -- COM несколько великоватая пушка для простой системы.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Страниц: 1 2 3 [Все]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines