| Автор |
С++ |
BlaXpirit
Користувач

Повідомлень: 20
Звідки: ЛФМЛ
Зареєстрований: 26.01.08 |
| Опубліковано 05-05-2008 22:28 |
|
|
|
Тема для запитань і відповідей про мову прогамування С++ |
|
| Автор |
RE: С++ |
BlaXpirit
Користувач

Повідомлень: 20
Звідки: ЛФМЛ
Зареєстрований: 26.01.08 |
| Опубліковано 05-05-2008 22:30 |
|
|
|
Люди, хтось знає, як створити бібліотеку (*.DLL) з різними функціями і т.д. на С++? Чи це взагалі неможливо..? |
|
| Автор |
RE: С++ |
webmaster
Головний Адміністратор

Повідомлень: 1136
Зареєстрований: 17.03.07 |
| Опубліковано 06-05-2008 00:35 |
|
|
Якщо можна створити *.exe файл значить можна створити і *.dll файл.
Для початку потрібно вказати властивості проекту, щоб воно компілювало в *.dll файл.
Наприклад у Студії коли створюєш проект, то там у діалоговому вікні можна вибрати DLL. Але також можна і потім змінити властивості проекту Project/Properties/Configuration Properties/General/Configuration Type (і унших версіях може бути по інкшому).
А далі іде сам код, який трохи відрізнається від коду звичайних аплікацій.
Приклад деяких функцій на мові С++
#include <windows.h> #include <string> using namespace std; extern "C" __declspec(dllexport) int __stdcall sum(int a, int b) { return a+b; } extern "C" __declspec(dllexport) int __stdcall sub(int a, int b) { return a-b; } extern "C" __declspec(dllexport) int __stdcall strlen2(LPSTR c) { string s(c); return s.size(); }
Приклад цих же функцій на мові Pascal
library DelphiDLL; {$APPTYPE CONSOLE} function sum(a,b : integer) : integer; stdcall; begin Result := a + b; end; function sub(a,b : integer) : integer; stdcall; begin Result := a-b; end; function strlen2(ins : PChar) : integer; stdcall; var s : string; begin s := ins; Result := length(s); end; exports sum, sub, strlen2; end. -
Модифікатором (extern "C") потрібний для того, щоб можна було викликати функції по назві. Бо компілятори С++ насправді переназивають функцію. У новій назві враховується кількість і типи параметрів. Це дає змогу сторювати функції з однаковими назвами, але різними параметрами, що у бінарних файлах (*.exe, *.dll) не допустимо.
А модифікатор "stdcall" щоб відбувалося однозначне розгортання стеку.
Змінив(ла) webmaster, 06-05-2008 00:47 |
|
| Автор |
RE: С++ |
BlaXpirit
Користувач

Повідомлень: 20
Звідки: ЛФМЛ
Зареєстрований: 26.01.08 |
| Опубліковано 06-05-2008 21:33 |
|
|
|
Дуже дякую. А чи можна в Delphi користуватися бібліотекою з C++? |
|
| Автор |
RE: С++ |
webmaster
Головний Адміністратор

Повідомлень: 1136
Зареєстрований: 17.03.07 |
| Опубліковано 07-05-2008 00:07 |
|
|
Звісно можна.
Головне щоб модифікари були потрібні вказані.
Ось наприклад код на мові C#, використання вище наведених фукнцій
namespace sol { class Program { [DllImport(@"a.dll", EntryPoint = "sum", CallingConvention = CallingConvention.StdCall)] private static extern int sum(int a, int b); static void Main(string[] args) { int a = 123; int b = 321; int res = sum(a, b); } } } -
Змінив(ла) webmaster, 07-05-2008 00:11 |
|
| Автор |
RE: С++ |
DixonD
Модератор
Повідомлень: 167
Звідки: ЛНУ ім. Івана Франка
Зареєстрований: 21.10.06 |
| Опубліковано 07-05-2008 08:45 |
|
|
В Delphi достатньо описати цю функцію, наприклад
function sum(a,b:integer);stdcall;cdecl; external 'a.dll';
Інший варіант - використати функцію LoadLibrary
Змінив(ла) webmaster, 08-05-2008 00:06 |
|
| Автор |
RE: С++ |
BlaXpirit
Користувач

Повідомлень: 20
Звідки: ЛФМЛ
Зареєстрований: 26.01.08 |
| Опубліковано 09-05-2008 18:39 |
|
|
В мене компілятор (Visual Studio 6.0) в DLL функцію sum перейменовує на _sum@8.
І ще одна проблема: ця функція в Delphi (з DLL) видає неправильні результати (якісь від'ємні числа). |
|
| Автор |
RE: С++ |
ibm
Користувач

Повідомлень: 422
Звідки: LPML
Зареєстрований: 21.02.07 |
| Опубліковано 05-06-2008 23:05 |
|
|
DixonD написав:
В Delphi достатньо описати цю функцію, наприклад
function sum(a,b:integer);stdcall;cdecl; external 'a.dll';
Не обов'язково писати назву функції?
function LoadLibraryEx(LibName: PChar; hFile: Longint; Flags: Longint): Longint; stdcall; external 'kernel32.dll' name 'LoadLibraryExA';
Pascal not dead! |
|
| Автор |
RE: С++ |
Oracle
Користувач
Повідомлень: 75
Звідки: LNU FAMI-13
Зареєстрований: 20.02.07 |
| Опубліковано 06-06-2008 12:18 |
|
|
|
Назву треба писати тільки якщо вона не співпадає з назвою функції в ДЛЛці. Наприклад в твому прикладі ти експортуєш функцію LoadLibraryEx, а в ДЛЛ вона називається LoadLibraryExA - в таких випадках назву писати треба. А от коли б ти експортував LoadLibraryExA, то назву можна б було не писати. |
|
| Автор |
RE: С++ |
ibm
Користувач

Повідомлень: 422
Звідки: LPML
Зареєстрований: 21.02.07 |
| Опубліковано 08-06-2008 11:55 |
|
|
Зрозуміло, дякую
Pascal not dead! |
|
| Автор |
RE: С++ |
ibm
Користувач

Повідомлень: 422
Звідки: LPML
Зареєстрований: 21.02.07 |
| Опубліковано 12-06-2008 22:15 |
|
|
Доречі!
webmaster написав:
library DelphiDLL; {$APPTYPE CONSOLE} function sum(a,b : integer) : integer; stdcall; begin Result := a + b; end; ... -
Хелп Дельфи каже: The $APPTYPE directive is meaningful only in a program. It should not be used in a library, unit, or package.
Pascal not dead! |
|
| Автор |
RE: С++ |
BlaXpirit
Користувач

Повідомлень: 20
Звідки: ЛФМЛ
Зареєстрований: 26.01.08 |
| Опубліковано 12-06-2008 22:27 |
|
|
Конкурс*! Хто зможе написати найменший код для копіювання одної char*-стрічки (p) в іншу (q) на С++?
Чим менший код - тим менша оцінка.
В кого найменша оцінка - той переможець!
*Призи переможцям не надаються  |
|
| Автор |
RE: С++ |
Oracle
Користувач
Повідомлень: 75
Звідки: LNU FAMI-13
Зареєстрований: 20.02.07 |
| Опубліковано 13-06-2008 10:19 |
|
|
XIII написав:
Конкурс*! Хто зможе написати найменший код для копіювання одної char*-стрічки (p) в іншу (q) на С++?
Чим менший код - тим менша оцінка.
В кого найменша оцінка - той переможець!
*Призи переможцям не надаються 
strcpy(q,p);  |
|
| Автор |
RE: С++ |
BlaXpirit
Користувач

Повідомлень: 20
Звідки: ЛФМЛ
Зареєстрований: 26.01.08 |
| Опубліковано 14-06-2008 18:30 |
|
|
Ха-ха! А де #include?
Без стандартних функцій! |
|
| Автор |
RE: С++ |
Oracle
Користувач
Повідомлень: 75
Звідки: LNU FAMI-13
Зареєстрований: 20.02.07 |
| Опубліковано 14-06-2008 22:49 |
|
|
ну тоді мінімум на що я спромігся це:
for (int i=0;p[i];) q[i]=p[i++];
П.С. тут вважається що q достатньо велика щоб вмістити p і заповнена нульовими символами.
Змінив(ла) Oracle, 14-06-2008 22:59 |
|
| Автор |
RE: С++ |
DixonD
Модератор
Повідомлень: 167
Звідки: ЛНУ ім. Івана Франка
Зареєстрований: 21.10.06 |
| Опубліковано 16-06-2008 08:15 |
|
|
До речі, на рахунок Delphi і dll. З власного досвіду можу сказати, що краще використовувати динамічне звязування замість статичного, тобто використовувати LoadLibrary. Просто якщо якісь проблеми з dll-кою, то наведеному вище використанні тупо не запуститься цілий проект, а так просто не буде працювати лише код, який юзає ту бібліотеку. Кусок коду з реальної проги:
unit Maps;
interface
uses Windows,SysUtils,Forms,Dialogs;
var
NewMSIMap:function :integer; cdecl;
//..............
implementation
var
LibraryHandle:integer;
//..............
initialization
LibraryHandle:=LoadLibraryA(PAnsiChar(ExtractFileDir(Application.ExeName)+'\maps.dll'));
if (LibraryHandle=0) then ShowMessage('Помилка при спробі завантаження maps.dll');
@NewMSIMap:=GetProcAddress(LibraryHandle,PAnsiChar('NewMSIMap'));
//..............
finalization
FreeLibrary(LibraryHandle);
end.
Змінив(ла) DixonD, 16-06-2008 08:16 |
|
| Автор |
RE: С++ |
BlaXpirit
Користувач

Повідомлень: 20
Звідки: ЛФМЛ
Зареєстрований: 26.01.08 |
| Опубліковано 26-06-2008 17:41 |
|
|
Oracle написав:
ну тоді мінімум на що я спромігся це:
for (int i=0;p[i];) q[i]=p[i++];
П.С. тут вважається що q достатньо велика щоб вмістити p і заповнена нульовими символами.
Оцінка 30
Тільки чому q має бути заповнена '\0' ?
Ну, добре, дам підказку. А якщо скористатися вказівниками*? *pointer
Змінив(ла) BlaXpirit, 27-06-2008 11:37 |
|