Форум программистов, компьютерный форум CyberForum.ru

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.93
pEntity
11 / 6 / 1
Регистрация: 12.12.2012
Сообщений: 391
#1

Как верно экспортить функцию? - C++

20.01.2014, 14:12. Просмотров 1950. Ответов 45
Метки нет (Все метки)

C++
1
2
3
4
5
6
7
#define _DECLARATOR_ __declspec(dllexport)
 
 
_DECLARATOR_ void __cdecl SumFunc()
{
    return;
}
C++
1
2
3
.text:10001000 ; void __cdecl SumFunc(void *__formal, void *__formal)
.text:10001000                 public ?SumFunc@@YAXXZ
.text:10001000 ?SumFunc@@YAXXZ proc near


__cdecl должно было удалить лишнии символы в стеке О_о

______________________________________________________________________________

C++
1
2
3
4
extern "C" void __declspec(dllexport) SumFunc()
{
    return;
}
C++
1
2
3
.text:10001000 ; void __cdecl SumFunc(void *__formal, void *__formal)
.text:10001000                 public _SumFunc
.text:10001000 _SumFunc        proc near
В этом варианте с __cdecl так же ничего не измениться.

________________________________________________________

C++
1
2
3
4
void __declspec(dllexport) SumFunc()
{
    return;
}
C++
1
2
3
.text:10001000 ; void __cdecl SumFunc(void *__formal, void *__formal)
.text:10001000                 public ?SumFunc@@YAXXZ
.text:10001000 ?SumFunc@@YAXXZ proc near

Так как же верно экспортить? Для чего extern "C" ? __declspec(dllexport) пихать перед void или после ? Как сделать, чтоб имя было без любых доп символов ?
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.01.2014, 14:12
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Как верно экспортить функцию? (C++):

Задача логические функции (составить функцию, которая определяет верно ли что сумма цифр числа четное число) - C++
Помогите нужно составить функцию, которая определяет верно ли что сумма цифр числа четное число. обязательно использовать логическую...

Перегрузка операций (Создать класс вещественных чисел (double); определить оператор +, как функцию-элемент и – как дружественную функцию) - C++
помогите решить пожалуйста Задание 2. Бинарная операция Создать класс вещественных чисел (double).. Определить оператор +, как...

Как правильно вызвать функцию с указателем на другую функцию как параметр - C++
Вот вариант: double f(double x) { ... } double k(double (*f)(double), double y) { ...

Как верно перевести формулу на язык c++? - C++
Приветствую! Столкнулся с такой задачей в университете на 1 курсе... нужно сделать лабораторную работу с программой на с, подробности во...

Как верно узнать размер указателя ? - C++
СBaseTest* pTest = { new СBaseTest, new СOther }; Нужно узнать размер pTest

как мне функцию одного класса в функцию базового вставить - C++
как мне функцию одного класса в функцию базового вставить??чет не хера не получается.... class Car { public : void...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
castaway
Эксперт С++
4881 / 3017 / 370
Регистрация: 10.11.2010
Сообщений: 11,078
Записей в блоге: 10
Завершенные тесты: 1
20.01.2014, 14:42 #2
А почему у тебя в коде нет параметров, а в дизасемблере целых два?
И где ты тут увидел что стек не удаляется?
pEntity
11 / 6 / 1
Регистрация: 12.12.2012
Сообщений: 391
20.01.2014, 14:50  [ТС] #3
Не знаю откуда там аргументы взялись. Если бы стек удалился, то функция была бы чистым именем, без всяких доп символов. Мне ведь нужно применить для этого __cdecl, но не выходит.
Убежденный
Системный программист
Эксперт С++
15503 / 7001 / 1105
Регистрация: 02.05.2013
Сообщений: 11,436
Завершенные тесты: 1
20.01.2014, 15:10 #4
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от pEntity Посмотреть сообщение
Если бы стек удалился, то функция была бы чистым именем, без всяких доп символов.
Вы путаете два понятия - соглашение о вызовах и декорацию имен.

Соглашение о вызовах (calling convention) определяет формат передачи аргументов в функцию.
Например, при _stdcall они передаются через стек, а затем удаляются оттуда вызываемой
функцией, в то время, как при _cdecl за очистку стека отвечает вызывающая сторона.

Декорация имен (name mangling) - "искажение" имен функций или данных во время экспорта.
Результат зависит от типа компоновки (extern "C" или extern "C++"), способа экспорта (DEF-файл
или директива __declspec(dllexport)) и типе соглашения о вызовах.

Чтобы в Visual C++ получить неискаженное имя, нужно или использовать DEF-файл, или
extern "C" + _cdecl.

Вот, набросал простенький примерчик:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
extern "C++"
__declspec(dllexport)
int _stdcall Dllexport_Cpp_Stdcall(int, int)
{
    return 0;
}
 
extern "C++"
__declspec(dllexport)
int _cdecl DllExport_Cpp_Cdecl(int, int)
{
    return 0;
}
 
extern "C"
__declspec(dllexport)
int _stdcall Dllexport_C_Stdcall(int, int)
{
    return 0;
}
 
extern "C"
__declspec(dllexport)
int _cdecl Dllexport_C_Cdecl(int, int)
{
    return 0;
}
 
extern "C++"
int _stdcall Deffile_Cpp_Stdcall(int, int)
{
    return 0;
}
 
extern "C++"
int _cdecl Deffile_Cpp_Cdecl(int, int)
{
    return 0;
}
 
extern "C"
int _stdcall Deffile_C_Stdcall(int, int)
{
    return 0;
}
 
extern "C"
int _cdecl Deffile_C_Cdecl(int, int)
{
    return 0;
}
Содержимое DEF-файла:
Код
LIBRARY "MyLibrary.dll"

EXPORTS
    Deffile_Cpp_Stdcall
    Deffile_Cpp_Cdecl
    Deffile_C_Stdcall
    Deffile_C_Cdecl
Вот какие имена получили экспортируемые функции:
Код
?DllExport_Cpp_Cdecl@@YAHHH@Z
?Dllexport_Cpp_Stdcall@@YGHHH@Z
Dllexport_C_Cdecl
_Dllexport_C_Stdcall@8
Deffile_C_Cdecl
Deffile_C_Stdcall
Deffile_Cpp_Cdecl
Deffile_Cpp_Stdcall
pEntity
11 / 6 / 1
Регистрация: 12.12.2012
Сообщений: 391
20.01.2014, 15:17  [ТС] #5
Спасибо большое !!!
Avazart
Эксперт С++
7145 / 5322 / 275
Регистрация: 10.12.2010
Сообщений: 23,556
Записей в блоге: 17
20.01.2014, 15:41 #6
Dynamic-Link Library: Теория + Практика
pEntity
11 / 6 / 1
Регистрация: 12.12.2012
Сообщений: 391
20.01.2014, 16:10  [ТС] #7
C++
1
2
3
.text:1000BA40 ; int __stdcall SumFunc()
.text:1000BA40                 public ?SumFunc@@YGHXZ
.text:1000BA40 ?SumFunc@@YGHXZ proc near
C++
1
2
3
4
5
6
extern "C++"
__declspec(dllexport)
int _stdcall SumFunc()
{
    return 0;
}

/* ------------------------------ */

C++
1
2
3
.text:1000BA40 ; int __cdecl SumFunc()
.text:1000BA40                 public ?SumFunc@@YAHXZ
.text:1000BA40 ?SumFunc@@YAHXZ proc near
C++
1
2
3
4
5
6
extern "C++"
__declspec(dllexport)
int _cdecl SumFunc()
{
    return 0;
}

/* ------------------------------ */

C++
1
2
3
.text:1000BA40 ; int __stdcall SumFunc()
.text:1000BA40                 public _SumFunc@0
.text:1000BA40 _SumFunc@0      proc near
C++
1
2
3
4
5
6
extern "C"
__declspec(dllexport)
int _stdcall SumFunc()
{
    return 0;
}
/* ------------------------------ */

C++
1
2
3
.text:1000BA40 ; int __cdecl SumFunc()
.text:1000BA40                 public _SumFunc
.text:1000BA40 _SumFunc        proc near
C++
1
2
3
4
5
6
extern "C"
__declspec(dllexport)
int _cdecl SumFunc()
{
    return 0;
}

/* ------------------------------ */

Всегда искажение. Я что-то не понимаю или делаю не так ? Но мне нужно, чтоб экспортная функция не искажалась, а имела такое же имя как и функция сама.

Работаю в VS 2012.

Или без DEF файла ни как ?

Добавлено через 12 минут
Понятно почему теперь подчеркивает.

А где это в VS ?

Прототип функции Test(int); мог быть преобразован компилятором, например в ?Test@@YAKH@Z.
Естественно, такое декорирование нам вообще не по душе. Избавиться от него можно объявляя все экспортируемые функции с модификатором extern "C" - тогда компилятор не будет искажать имя функции.

Однако, как мы видим, нижние подчёркивание всё же добавилось.
Это один из нюансов среды C++ Builder. Однако, можно отучить его добавлять нижнее подчёркивание таким образом:
Project -> Options -> C++ Compiler -> Output -> Generate underscores on symbol names - перевести в состояние false.
И какая разница между __cdecl и _cdecl ?
Avazart
Эксперт С++
7145 / 5322 / 275
Регистрация: 10.12.2010
Сообщений: 23,556
Записей в блоге: 17
20.01.2014, 16:17 #8
Цитата Сообщение от pEntity Посмотреть сообщение
Понятно почему теперь подчеркивает.
А где это в VS ?
То по большей части для С++Builder

Добавлено через 2 минуты
Цитата Сообщение от pEntity Посмотреть сообщение
Всегда искажение. Я что-то не понимаю или делаю не так ? Но мне нужно, чтоб экспортная функция не искажалась, а имела такое же имя как и функция сама.
Используй extern "C" не будет искажений.
Хотя стоп... как ты хочешь что бы ф-ция выглядела, и что ты имеешь ввиду под искажением?
pEntity
11 / 6 / 1
Регистрация: 12.12.2012
Сообщений: 391
20.01.2014, 17:49  [ТС] #9
Вот как тут:

C++
1
2
3
4
5
6
extern "C"
__declspec(dllexport)
int _cdecl SumFunc()
{
    return 0;
}
Только, чтоб было без подчеркивания
C++
1
_
SumFunc

Просто чистое имя функции. И какую роль играет тут _cdecl ? Потому что, что с ним, что без него ничего не меняется, может он не нужен когда используется extern "C" ?
Avazart
Эксперт С++
7145 / 5322 / 275
Регистрация: 10.12.2010
Сообщений: 23,556
Записей в блоге: 17
20.01.2014, 18:01 #10
Цитата Сообщение от pEntity Посмотреть сообщение
Только, чтоб было без подчеркивания
Какого подчекивания ?
pEntity
11 / 6 / 1
Регистрация: 12.12.2012
Сообщений: 391
20.01.2014, 18:03  [ТС] #11
C++
1
2
3
.text:1000BA40 ; int __cdecl SumFunc()
.text:1000BA40                 public _SumFunc
.text:1000BA40 _SumFunc        proc near
_SumFunc
Avazart
Эксперт С++
7145 / 5322 / 275
Регистрация: 10.12.2010
Сообщений: 23,556
Записей в блоге: 17
20.01.2014, 18:07 #12
Ну так в первой ф-ции нет искажения ?

Код
int __cdecl SumFunc()
Добавлено через 2 минуты
Цитата Сообщение от pEntity Посмотреть сообщение
И какую роль играет тут _cdecl ?
Соглашение вызова
pEntity
11 / 6 / 1
Регистрация: 12.12.2012
Сообщений: 391
20.01.2014, 18:11  [ТС] #13
Ну это же не экспортная функция.
Avazart
Эксперт С++
7145 / 5322 / 275
Регистрация: 10.12.2010
Сообщений: 23,556
Записей в блоге: 17
20.01.2014, 18:14 #14
Цитата Сообщение от pEntity Посмотреть сообщение
Ну это же не экспортная функция.
А какая импортная, заморская ?
pEntity
11 / 6 / 1
Регистрация: 12.12.2012
Сообщений: 391
20.01.2014, 18:20  [ТС] #15
С __declspec(dllexport)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.01.2014, 18:20
Привет! Вот еще темы с ответами:

Как сделать, чтобы 2 одинаковых перегруженных оператора выполнялись верно - C++
Всем привет! Столкнулся с такой ситуацией, что мне понадобилось использовать 2 перегруженных одинаковых оператора, все конечно же...

не могу разобраться как написать функцию сортировки и исправить функцию добавления в стек - C++
#include <iostream> #include<Windows.h> using namespace std; struct NE{ int x; NE *pnext,*ppor,*cur;}; class SPISOK { NE...

Как передать указатель на функцию в функцию - C++
И как с ней работать?

Как сделать функцию, возвращающую указатель на функцию (которая в свою очередь возвращает указатель на массив) - C++
Изучаю c++ по одной книжке.Она говорить не умеет.. Так вот понадобилось написать функцию,которая как параметр получает указатель на...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
20.01.2014, 18:20
Ответ Создать тему
Опции темы

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