Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Akylax
15 / 0 / 0
Регистрация: 27.11.2012
Сообщений: 93
#1

Написание dll - библиотеки и ее открытие средствами Delphi - C++

16.10.2013, 14:40. Просмотров 865. Ответов 16
Метки нет (Все метки)

Есть некоторая dll-библиотека, которая вычисляет площадь и периметр n-угольника. Лабораторная была на Delphi, решил попробовать написать dll-ку средствами языка C++ (на Visual Studio)
На msdn, нашел алгоритм написания:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//Simple.h
namespace dllspace{
    #define M_PI 3.1415926535897932384626433832795
    class dllclass
    {
    public:
        static __declspec(dllexport) double Square(double n, double b);
            
    public:
        static __declspec(dllexport) double Perimeter(double n, double b);
    };
}
//SimpleCPP.cpp
#include <math.h>
#include <stdexcept>
#include "SimpleH.h"
namespace dllspace
    {
     double dllclass::Square(double n, double b)
            {
             return( (1/4)*n*b*b*(1/tan(M_PI/n)));
            } 
    double dllclass::Perimeter(double n, double b)
        {
        return (n*b);
        }
    }
Открываю в приложении, которое динамически(т.е. в процессе выполнения) загружает dll-ку. Приложение 100% работает, если использовать dll-ку собранную в delphi.
P.S. Использовал соглашение cdecl
Кликните здесь для просмотра всего текста

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//Polygon.dll
library Polygon;
 
uses
  SysUtils,
  Classes,
  Math;
 
{$R *.res}
 
Function sq_polygon(n,b:Real):Real; stdcall;
begin
Result:=(1/4)*n*b*b*Cotan(Pi/n);
end;
Function perimeter_polygon(n,b:Real):Real; stdcall;
begin
Result:=n*b;
end;
 
Exports
 sq_polygon index 1, perimeter_polygon index 2;
begin
end.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//App_polygon.pas
unit App_polygon;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    valve: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
   //CONST DLLName='Polygon.dll'; // имя DLL
   CONST DLLName='SimpleDLL.dll'; // имя DLL
  Type
  TAllFunc = Function(n,b:Real):Real; cdecl;//stdcall;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.Button1Click(Sender: TObject);
Var
  n,b:Real;
  Square:TAllFunc;
  Perimeter:TAllFunc;
  flag:Boolean;
  Handle:LongInt;
begin
  flag:=false;
  if( Edit1.Text <> '') then
  b:=StrToFloat(Edit1.Text)
  else
    ShowMessage('Введите параметр b!');
  if( Edit2.Text <> '')  then
    begin
    n:=StrToFloat(Edit2.Text);
    flag:=true;
    end
  else
    ShowMessage('Введите параметр n!');
  if(flag=true) then
  begin
     //Загружаем библиотеку
      Handle:=LoadLibrary(DLLName);
      if(Handle<>0) then
      begin
      @Square := GetProcAddress(Handle,PChar(LongInt(1)));
      @Perimeter := GetProcAddress(Handle,PChar(LongInt(2)));
 
     IF Assigned(Square) then
  Label5.Caption:=FloatToStrF(Square(n,b),ffFixed,10,4)
                   else
                   ShowMessage('Ошибка доступа к библиотеке(Sq) '+DLLName);
    IF Assigned(Perimeter) then
  Label6.Caption:=FloatToStrF(Perimeter(n,b),ffFixed,10,4)
                            else
                           ShowMessage('Ошибка доступа к библиотеке(Per) '+DLLName);
      end //Handle <>0
      else ShowMessage('Ошибка загрузки библиотеки'+DLLName);
   FreeLibrary(handle);
  end;//flag=true
 
end;
 
end.

А если использовать эту, происходит странное. Она полностью пропускает функцию Square, и вызывает функцию Perimeter, причем записывает ф-ю Perimeter в первую переменную, которая хранит ссылку на функцию из dll - библиотеки. Вторая такая переменная содержит результат 0.0.
Как можно проиндексировать функции в dll-ке, написанной на c++?
Или может кто знает другие пути решения?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.10.2013, 14:40
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Написание dll - библиотеки и ее открытие средствами Delphi (C++):

Написание библиотеки - C++
Всем привет, расскажите плз, как написать свою библиотеку, а то что-то не могу понять. Если что, то моя IDE: Visual Studio 2010. P.S....

Написание библиотеки в С++ для вызова в C# - C++
помогите никак не получается :( вот я создал проект dll, написал в .h-нике #ifdef DLL_EXPORTS #define DLL_API __declspec(dllexport) ...

Написание пакетной утилиты ДОС средствами языка высокого уровня - C++
помогите с лабораторной пожалуйста. Тема: Написание пакетной утилиты ДОС средствами языка высокого уровня Цель: Освоить средства...

Написание библиотеки для воспроизведения MP3 - C++
Хочу вкупе своей программе добавить библиотеку для МР3. Можно ссылочек на то, как воспроизводить звук, и то, как устроен фаил? Если нужно...

Работа со звуком средствами библиотеки мультимедиа Windows - C++
Здравствуйте,есть программа которая снимает звук с микрофона. Она работает не полностью корректно. Проблема заключается в том,что если...

Написание и использование DLL - C++
Доброго времени суток! При попытке написать элементарную DLL возникло несколько вопросов: 1) Почему без указания экспорта в...

16
palva
2685 / 1912 / 287
Регистрация: 08.06.2007
Сообщений: 7,033
Записей в блоге: 4
16.10.2013, 15:41 #2
Чтобы проиндексировать, нужно подключить к проекту Visual Studio def-файл, где описываются все экспорты библиотеки с именами и индексами.

Добавлено через 42 минуты
Код
simple.h
#define M_PI 3.1415926535897932384626433832795
extern "C" {
double Square(double, double);
double Perimeter(double, double);
}

simple.cpp
#include <math.h>
#include "simple.h"

double Square(double n, double b)
{
    return( (1/4)*n*b*b*(1/tan(M_PI/n)));
} 
double Perimeter(double n, double b)
{
    return (n*b);
}

simple.def
LIBRARY	"simpledll"
EXPORTS
Square @1
Perimeter @2
0
palva
2685 / 1912 / 287
Регистрация: 08.06.2007
Сообщений: 7,033
Записей в блоге: 4
16.10.2013, 15:47 #3
файл dll
0
Вложения
Тип файла: zip simpledll.dll.zip (7.8 Кб, 4 просмотров)
Akylax
15 / 0 / 0
Регистрация: 27.11.2012
Сообщений: 93
16.10.2013, 20:59  [ТС] #4
Цитата Сообщение от palva Посмотреть сообщение
simple.def
LIBRARY "simpledll"
EXPORTS
Square @1
Perimeter @2
Теперь он не может получить ссылки на функции, если переписать код.
Цитата Сообщение от palva Посмотреть сообщение
файл dll
Скачивал ваш, там даже библиотеку загрузить не может. У меня подозрение, а среда вообще учитывает этот Def-файл?
0
ValeryS
Модератор
6729 / 5138 / 484
Регистрация: 14.02.2011
Сообщений: 17,244
16.10.2013, 21:13 #5
Akylax,
Мне конечно лень разбираться , но так на вскидку я не увидел слов(ключевых) extern "C"
все дело в том что без них в библиотеке не будет функции Square а будет какая то Square@d2..ну и так далее
можно проверить например PE Explorer
язык С++кодирует в имени функции все параметры этой функции( причем каждый компилятор по своему)
и если бы ты писал на Булдере то Делфи бы тебя понял(как никак одна фирма) но ты пишешь на Визуале( там своя кодировка) посему и нужно включать эти волшебные слова(extern "C") тогда и будет твоя функция иметь вид Square
правда параметры на твоей совести,если не правильно отдашь.то одному Биллу известо, что будет
0
Akylax
15 / 0 / 0
Регистрация: 27.11.2012
Сообщений: 93
16.10.2013, 21:18  [ТС] #6
Цитата Сообщение от ValeryS Посмотреть сообщение
язык С++кодирует в имени функции все параметры этой функции( причем каждый компилятор по своему)
и если бы ты писал на Булдере то Делфи бы тебя понял(как никак одна фирма) но ты пишешь на Визуале( там своя кодировка)
Этого я и боялся.
Цитата Сообщение от ValeryS Посмотреть сообщение
я не увидел слов(ключевых) extern "C"
все дело в том что без них в библиотеке не будет функции Square а будет какая то Square@d2
А куда ставить то? в .cpp? не канает.
0
ValeryS
Модератор
6729 / 5138 / 484
Регистрация: 14.02.2011
Сообщений: 17,244
16.10.2013, 21:32 #7
Цитата Сообщение от Akylax Посмотреть сообщение
А куда ставить то? в .cpp? не канает.
ну не знаю
примерно так
Цитата Сообщение от Akylax Посмотреть сообщение
double dllclass::Square(double n, double b)
C++
1
extern "C" double dllclass::Square(double n, double b)
вот тебе пара ссылок про эту фигню
extern
http://msdn.microsoft.com/ru-ru/library/0603949d.aspx
а вообще почитай что такое искажение имен
простой пример
C++
1
2
int max(int a,int b)
char max(char a, char b)
в Си даст ошибку компиляции, а в плюсах нет
почему ?
все очень просто плюсы в имя функции забивают количество и тип параметров, причем каждая фирма по своему

Добавлено через 2 минуты
Akylax,
скачай себе PE Explorer(до 30 дней он бесплатен)
и скорми ему две ДЛЛки с extern "C" и без
и увидишь разницу в именах функций
0
palva
2685 / 1912 / 287
Регистрация: 08.06.2007
Сообщений: 7,033
Записей в блоге: 4
16.10.2013, 21:45 #8
Цитата Сообщение от Akylax Посмотреть сообщение
А куда ставить то? в .cpp? не канает.
У меня показано, куда.
Откровенно говоря, я не понял ваши трудности. Вот эту фразу:
Цитата Сообщение от Akylax Посмотреть сообщение
Теперь он не может получить ссылки на функции, если переписать код.
Что вы пытаетесь сделать и что происходит?
Цитата Сообщение от Akylax Посмотреть сообщение
Скачивал ваш, там даже библиотеку загрузить не может.
Где там?

Добавлено через 12 минут
Цитата Сообщение от ValeryS Посмотреть сообщение
скачай себе PE Explorer(до 30 дней он бесплатен)
Вы что, не можете посмотреть экспорты dll ? Вы же в Delphi работаете. У вас есть утилита tdump. Вот вырезаю из листинга из ее выдачи:
Код
Section:             Exports
File Offset:         00003A00 (14848)
  Flags:             00000000
  Time Stamp:        525E7AC7 : Wed Oct 16 15:38:47 2013
  Major Version:     0000
  Minor Version:     0000

Exports from simpledll.dll
  2 exported name(s), 2 export addresse(s).  Ordinal base is 1.
  Sorted by Name:
    RVA      Ord. Hint Name
    -------- ---- ---- ----
    000110D2    2 0000 Perimeter
    00011050    1 0001 Square
Добавлено через 50 секунд
Видны внешние имена и индексы. Можете загружать по именам, можете по индексам.
0
ValeryS
Модератор
6729 / 5138 / 484
Регистрация: 14.02.2011
Сообщений: 17,244
16.10.2013, 21:54 #9

Не по теме:

Цитата Сообщение от palva Посмотреть сообщение
Вы что, не можете посмотреть экспорты dll ? Вы же в Delphi работаете.
и в вижуале есть эта приблуда
просто я PE Explorer порекомендовал, он более нагляден
закачал в него ДЛЛку или ЕХЕшку а он покажет и импорт и экспорт и отложенный импорт и по именам и по номерам


вот кстати для ТС еще несколько ссылок
http://www.codenet.ru/progr/bcb/dll.php
http://ru.wikibooks.org/wiki/DLL
http://www.rsdn.ru/article/baseserv/dlluse.xml
0
palva
2685 / 1912 / 287
Регистрация: 08.06.2007
Сообщений: 7,033
Записей в блоге: 4
16.10.2013, 22:12 #10
Вот работающая программа Delphi
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{$APPTYPE CONSOLE}
program pg88;
uses Windows;
Type
    TAllFunc = Function(n,b:Real):Real; cdecl;//stdcall;
var
    Handle:HModule;
    Square, Perimeter: TAllFunc;
    n,b: Real;
begin
    Handle:=LoadLibrary('simpledll.dll');
    if(Handle<>0) then
    begin
        @Square := GetProcAddress(Handle,PChar(LongInt(1)));
        @Perimeter := GetProcAddress(Handle,PChar(LongInt(2)));
        n := 3.0;
        b := 4.0;
        WriteLn(Perimeter(n,b));
    end;
end.
Square возвращает нуль, поскольку вы неправильно реализовали ее на си.
C++
1
1/4
Это выражение дает нуль. Надо писать
C++
1
1.0/4.0
Добавлено через 2 минуты
Цитата Сообщение от palva Посмотреть сообщение
Вы что, не можете посмотреть экспорты dll ?
ValeryS, Извините, это я обращался к Akylax,
1
ValeryS
16.10.2013, 22:45
  #11

Не по теме:

Цитата Сообщение от palva Посмотреть сообщение
ValeryS, Извините, это я обращался к Akylax,
да не, нормально
у каждой более менее серьезной ИДЕшки есть прога чтобы прочитать импорт экспорт
но иногда сторонние более удобны

0
Akylax
15 / 0 / 0
Регистрация: 27.11.2012
Сообщений: 93
16.10.2013, 22:54  [ТС] #12
Цитата Сообщение от palva Посмотреть сообщение
Вот работающая программа Delphi
У меня она и так работает, я не это спрашивал
Цитата Сообщение от ValeryS Посмотреть сообщение
вот кстати для ТС еще несколько ссылок
Википедия то зачем
Цитата Сообщение от palva Посмотреть сообщение
PE Explorer
Он не решит проблему
Цитата Сообщение от palva Посмотреть сообщение
Скачивал ваш, там даже библиотеку загрузить не может.
Где там?
Вы загрузили на сайт архив с ддлкой, я и ее пробнул. Вот такой результат получил.
Цитата Сообщение от palva Посмотреть сообщение
У вас есть утилита tdump. Вот вырезаю из листинга из ее выдачи:
Господи, что за ужас!
Цитата Сообщение от palva Посмотреть сообщение
Можете загружать по именам
В статичном методе пробовал по именам грузить(еще старая версия dll-ки была) ругался на недоступность к точкам доступа процедуры
Цитата Сообщение от ValeryS Посмотреть сообщение
extern "C" double dllclass::Square(double n, double b)
попробую
0
palva
2685 / 1912 / 287
Регистрация: 08.06.2007
Сообщений: 7,033
Записей в блоге: 4
16.10.2013, 23:03 #13
Цитата Сообщение от Akylax Посмотреть сообщение
У меня она и так работает, я не это спрашивал
Вы сказали, что у вас моя dll не грузится. У меня грузится и выполняется. Это работающий пример.
Цитата Сообщение от Akylax Посмотреть сообщение
В статичном методе пробовал по именам грузить(еще старая версия dll-ки была) ругался на недоступность к точкам доступа процедуры
Тот же вопрос: неужели вы не могли посмотреть имя экспорта и указать правильное имя? Откройте dll в текстовом редакторе, наконец, и поищите имя.
0
ValeryS
Модератор
6729 / 5138 / 484
Регистрация: 14.02.2011
Сообщений: 17,244
16.10.2013, 23:05 #14
Цитата Сообщение от Akylax Посмотреть сообщение
Википедия то зачем
это ты про wikibooks?
ну чтобы знал что есть экспорт что есть импорт
информация нужно брать отовсюду(правда критично к ней относится)
Цитата Сообщение от Akylax Посмотреть сообщение
Он не решит проблему
конечно не решит
но покажет, что экспортирует твоя ДЛЛка
Цитата Сообщение от Akylax Посмотреть сообщение
class dllclass
не заметил сначала
забудь в ДЛЛках про классы, это дело тонкое( тоже искажение имен) поройся в инете про классы в ДЛЛках и поймешь что чаше всего они не нужны, но если так хочется то полностью переписывай интерфейс
ибо трудно левой программе создать объект класса
посмотри как реализован DirectX
0
Avazart
Эксперт С++
7236 / 5432 / 304
Регистрация: 10.12.2010
Сообщений: 24,143
Записей в блоге: 17
16.10.2013, 23:17 #15
Цитата Сообщение от ValeryS Посмотреть сообщение
забудь в ДЛЛках про классы
Да ибо "форматы" в Delphi и VC++ разные для классов.

Можно попробовать писать в Delphi/С++Builder там должно работать.
0
16.10.2013, 23:17
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.10.2013, 23:17
Привет! Вот еще темы с ответами:

Создание dll библиотеки c++ - C++
Есть проект, где много заголовочных файлов. Как собрать dll библиотеку так, чтобы потом использовать только 1 заголовочный файл, а...

Подключение dll библиотеки - C++
Привет. Для работы с шаговым двигателем мне необходимо воспользоваться приложенной к нему dll библиотекой в которой как раз и реализованы...

Компиляция dll библиотеки - C++
Как правильно скомпилировать dll библиотеку, чтобы имена методов не изменялись? Например, у меня есть метод с именем Java_Test_test, а...

открытие и считывание из .dll - C++
Доброго времени суток. Необходимо с помощью С++ открыть файл формата .dll в бинарном виде. После чего вытащить из этого бинарного файла всю...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.