PDA

View Full Version : سوال: چگونه یک Dll بسازیم



kia.celever
چهارشنبه 01 تیر 1390, 12:00 عصر
سلام من میخواستم ببینم چه طوری میتونیم توی یه برنامه کدمون رو به صورت Dll خروجی بگیریم و چه طور توی یه برنامه ی دیگه از اون Dll استفاده کنیم ؟

r00tkit
چهارشنبه 01 تیر 1390, 12:57 عصر
از گوگل استفاده کن :
http://www.flipcode.com/archives/Creating_And_Using_DLLs.shtml


کامل بخون همه چی رو توضیح داده

djsohrab2007
چهارشنبه 02 شهریور 1390, 18:30 عصر
لینک زیر از MSDN است ، خوب توضیح داده :

http://msdn.microsoft.com/en-us/library/ms235636.aspx

BORHAN TEC
چهارشنبه 02 شهریور 1390, 18:34 عصر
سلام من میخواستم ببینم چه طوری میتونیم توی یه برنامه کدمون رو به صورت Dll خروجی بگیریم و چه طور توی یه برنامه ی دیگه از اون Dll استفاده کنیم ؟
در کدام IDE؟

djsohrab2007
پنج شنبه 03 شهریور 1390, 02:22 صبح
سلام،
حالا که بحث dll دوباره باز شد بزارید منم سوالم را بپرسم البته بگم کل فروم و گوگل و ... را گشتم جواب برای سوالم زیاد هست ، همه را خواندم ولی راستش هیچی نفهمیدم الان حدود 5 ساعته که دارم تو وب می گردم اما حاصلش 0

سوال : می دانم __declspec(dllexport) برای فرستادن تابع یا متغیر به خارج از DLL است ( یعنی می زاره برنامه های دیگه از این تابع استفاده کنند ) ولی __declspec(dllimport ) برای چه کاری هست ؟
یکی گفته اگر در کدی که می خواهیم از dll استفاده کنیم امضای تابع ( پروتایپ تابع ) را با dllimport بنویسیم بهتره و نبودش ایراد نیست بلکه سرعت را کم می کنه : http://msdn.microsoft.com/en-us/library/zw3za17w.aspx
یکی دیگه گفته باعث وارد شدن اطلاعات به برنامه می شود، خط اول : http://msdn.microsoft.com/en-us/library/8fskxacy.aspx
یکی هم که اصلا نفهمیدم چی گفته : http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c9855 ، اونجایی که کد زیر را نوشته نگاه کنید :
#if defined DLL_EXPORT #define DECLDIR __declspec(dllexport) #else #define DECLDIR __declspec(dllimport) #endif

آخرش نفهمیدم چی شد ، یکی لطف کنه فارسی و به زیانی ساده توضیح بده که که این dllimport دقیقا چی هست ؟ فقط به این سایت و اون سایت پاس ندید لطفا!

pe32_64
پنج شنبه 03 شهریور 1390, 17:09 عصر
__declspec(dllimport) برای فراخوانی (استفاده از) کلاسها-توابه-متغیر هایی هستند که در یک فایل DLL قرار دارند.

djsohrab2007
پنج شنبه 03 شهریور 1390, 17:51 عصر
__declspec(dllimport) برای فراخوانی (استفاده از) کلاسها-توابه-متغیر هایی هستند که در یک فایل DLL قرار دارند.

سلام،
ببین آخه ما توی خود dll از dll استفاده نمی کنیم که !!!

توی همون لینک بالا که برای شما فرستادم ، یک dll به فرم زیر تعریف کرده :
فایل .h بصورت زیر :


#ifndef _DLL_TUTORIAL_H_
#define _DLL_TUTORIAL_H_
#include <iostream>
#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
extern "C" {
DECLDIR int Add( int a, int b );
DECLDIR void Function( void );
}
#endif


فایل .cpp به صورت زیر :

#include <iostream>
#include "DLL_Tutorial.h"
#define DLL_EXPORT
extern "C" {
DECLDIR int Add( int a, int b )
{
return( a + b );
}
DECLDIR void Function( void )
{
std::cout << "DLL Called!" << std::endl;
}
}

حالا نگاه کن توی تعریف dll هم از dllimport استفاده کرده !!!!! درحالی که توی dll باید فقط export می کرد و توی برنامه ای که می خواست از این dll استفاده کنه import می کرد ( البته طبق تعریف شما از dllimport )

djsohrab2007
پنج شنبه 03 شهریور 1390, 23:43 عصر
یکی بی زحمت جواب ما را بده ، راستی یک سوال دیگه : اینکه یک هندل از dll می گیریم و با اشاره گر به تابع ف تابع های آن را فراخوانی می کنیم را بلدم ولی اگر dll من دارای کلاس باشه که چند تا از توابع static آن export شده باشه. بلد نیستم ، با LoadLibrary به dll وصل میشما ولی با GetProcAddress نمی توانم آدرس تابع را بگیرم ( اگر داخل کلاس نبود می تونم ولی اگر متد کلاس باشه نمی تونم ) میشه یکی یاد بده ؟

r00tkit
جمعه 04 شهریور 1390, 00:26 صبح
سلام

پیام خصوصی دادی امدم سر بزنم ببینم چه خبره حوصله ندارم از اول بخونم سوالات رو دقیق بپرس توضیح بدم

برای اخرین سوالت : از همنون Dllimport باید استفاده کنی فقط چند تا نکته داره این مقاله رو نخوندم ولی فکر کنم کمکت کنه

http://www.codeproject.com/KB/DLL/classesexportedusingLL.aspx

توصیه می کنم فصل 19 کتاب windows via c/c++ رو بخونی حتما همهی سوالات حل می شه

djsohrab2007
جمعه 04 شهریور 1390, 02:13 صبح
سلام

پیام خصوصی دادی امدم سر بزنم ببینم چه خبره حوصله ندارم از اول بخونم سوالات رو دقیق بپرس توضیح بدم

برای اخرین سوالت : از همنون Dllimport باید استفاده کنی فقط چند تا نکته داره این مقاله رو نخوندم ولی فکر کنم کمکت کنه

http://www.codeproject.com/KB/DLL/classesexportedusingLL.aspx

توصیه می کنم فصل 19 کتاب windows via c/c++ رو بخونی حتما همهی سوالات حل می شه

سلام

دمت گرم وقت گذاشتی
شرح کامل داستان و کل سوال هایی که من درمورد dll دارم :

سوال 1:
ببین من درست فرق dllimport را با dllexport متوجه نشدم، یکی از دوستان گفت dllimport برای استفاده از توابع و کلاسهای تعریف شده داخل یک dll است، اگر اینطوره پس چرا
در سایت http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c9855 از خود dllimport در تعریف dll استفاده کرده ، یک dll به صورت زیر تعریف کرده :

فایل .h :

#ifndef _DLL_TUTORIAL_H_
#define _DLL_TUTORIAL_H_
#include <iostream>
#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
extern "C" {
DECLDIR int Add( int a, int b );
DECLDIR void Function( void );
}
#endif





فایل .cpp :

#include <iostream>
#include "DLL_Tutorial.h"
#define DLL_EXPORT
extern "C" {
DECLDIR int Add( int a, int b )
{
return( a + b );
}
DECLDIR void Function( void )
{
std::cout << "DLL Called!" << std::endl;
}
}



یعنی اگر فقط برای استفاده بود توی تعریف dll که خودش نمی خواهیم استفاده کنیم که پس لزومی بهش نداریم وفقط به dllexport نیاز است تا تابع را با آن به خارج از dll بفرستیم.

سوال 2:
ببین برای استفاده از dll دو راه کلی وجود داره دیگه به نامهای Implicit Linking و Explicit Linking با روش اول کاری ندارم ، در روش دوم اگر dll خود را با کلاس نوشته باشیم. موقع استفاده از dll برای دستیابی به متدها چکاری باید انجام دهیم ؟
در مقاله ای که شما فرستادید برای دستیابی به متدها از هدرفایل ( فایل .h ) خود dll استفاده کرده ولی همه ی ما می دانیم که برتری استفاده از dll در این روش نسبت به روش Implicit Linking این است که در این روش نیازی به فایل .h و فایل .llib خود dll نیست ( منبع : http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c9855 )

سوال 3 :
در یک سایتی قبلا خونده بودم که یک روش دیگر برای استفاده از dll روش Delay Load Import است ولی یادمه که مثال خودش هم کامپایل نمی شد من در مورد این توی MSDN فقط یه چند خطی پیدا کردم
(http://msdn.microsoft.com/en-us/library/yx9zd12s.aspx ) اما مثال نزده بود که یاد بگیرم ، می خواستم ببینم اگر می شود این روش را با یک مثال توضیح دهید

سوال 4 :
هر جا که مطلبی در مورد dll خوندم ، گفته بود ساخت و استفاده یک dll ساده ، مگه dll پیچیده هم داریم ؟ اگر داریم چیه و تعریفش چطوریه ؟

بازم ممنون و شرمنده که وقت شما را گرفتم ، فقط یک در خواست دیگه ، اگه میشه لطف کن رفرنس انگلیسی نده که سخت مشکل دارم، لطف کن ساده و کامل به فارسی توضیح بده. فرض کن داری یک مقاله آموزشی می نویسی

djsohrab2007
جمعه 04 شهریور 1390, 02:34 صبح
راستی در مورد اون کتابی که گفتی من ندارمش لینک دانلود ویا اسم کامل کتاب را بنویس تا پیداش کنم

djsohrab2007
جمعه 04 شهریور 1390, 02:37 صبح
من اون مقاله ای که فرستادی را دوباره نگاه کردم دیدم که اون وقتی کار می کنه که کل کلاس export شده باشه ، چون آدرس constractor کلاس را بدست میاره ، حالا اگر فقط چند متد static کلاس export شده باشه چی ؟

djsohrab2007
جمعه 04 شهریور 1390, 05:59 صبح
سلام

دمت گرم وقت گذاشتی
شرح کامل داستان و کل سوال هایی که من درمورد dll دارم :

سوال 1:
ببین من درست فرق dllimport را با dllexport متوجه نشدم، یکی از دوستان گفت dllimport برای استفاده از توابع و کلاسهای تعریف شده داخل یک dll است، اگر اینطوره پس چرا
در سایت http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c9855 از خود dllimport در تعریف dll استفاده کرده ، یک dll به صورت زیر تعریف کرده :

فایل .h :

#ifndef _DLL_TUTORIAL_H_
#define _DLL_TUTORIAL_H_
#include <iostream>
#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
extern "C" {
DECLDIR int Add( int a, int b );
DECLDIR void Function( void );
}
#endif





فایل .cpp :

#include <iostream>
#include "DLL_Tutorial.h"
#define DLL_EXPORT
extern "C" {
DECLDIR int Add( int a, int b )
{
return( a + b );
}
DECLDIR void Function( void )
{
std::cout << "DLL Called!" << std::endl;
}
}



یعنی اگر فقط برای استفاده بود توی تعریف dll که خودش نمی خواهیم استفاده کنیم که پس لزومی بهش نداریم وفقط به dllexport نیاز است تا تابع را با آن به خارج از dll بفرستیم.

سوال 2:
ببین برای استفاده از dll دو راه کلی وجود داره دیگه به نامهای Implicit Linking و Explicit Linking با روش اول کاری ندارم ، در روش دوم اگر dll خود را با کلاس نوشته باشیم. موقع استفاده از dll برای دستیابی به متدها چکاری باید انجام دهیم ؟
در مقاله ای که شما فرستادید برای دستیابی به متدها از هدرفایل ( فایل .h ) خود dll استفاده کرده ولی همه ی ما می دانیم که برتری استفاده از dll در این روش نسبت به روش Implicit Linking این است که در این روش نیازی به فایل .h و فایل .llib خود dll نیست ( منبع : http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c9855 )

سوال 3 :
در یک سایتی قبلا خونده بودم که یک روش دیگر برای استفاده از dll روش Delay Load Import است ولی یادمه که مثال خودش هم کامپایل نمی شد من در مورد این توی MSDN فقط یه چند خطی پیدا کردم
(http://msdn.microsoft.com/en-us/library/yx9zd12s.aspx ) اما مثال نزده بود که یاد بگیرم ، می خواستم ببینم اگر می شود این روش را با یک مثال توضیح دهید

سوال 4 :
هر جا که مطلبی در مورد dll خوندم ، گفته بود ساخت و استفاده یک dll ساده ، مگه dll پیچیده هم داریم ؟ اگر داریم چیه و تعریفش چطوریه ؟

بازم ممنون و شرمنده که وقت شما را گرفتم ، فقط یک در خواست دیگه ، اگه میشه لطف کن رفرنس انگلیسی نده که سخت مشکل دارم، لطف کن ساده و کامل به فارسی توضیح بده. فرض کن داری یک مقاله آموزشی می نویسی




راستی در مورد اون کتابی که گفتی من ندارمش لینک دانلود ویا اسم کامل کتاب را بنویس تا پیداش کنم




من اون مقاله ای که فرستادی را دوباره نگاه کردم دیدم که اون وقتی کار می کنه که کل کلاس export شده باشه ، چون آدرس constractor کلاس را بدست میاره ، حالا اگر فقط چند متد static کلاس export شده باشه چی ؟




ببین خلاصه ی خلاصه ، لطف کن جواب سوالات بالا را با dll ی که به صورت زیر تعریف شده جواب بده ، اگر هر کدوم از سوالات بالا احتیاج به مثال دیگری داشت خودت زحمتش را بکش :

فایل .h :


#pragma once

#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif

namespace MathFuncs
{
class MyMathFuncs
{
public:
// Returns a + b
static DECLDIR double Add(double a, double b);

// Returns a - b
static double Subtract(double a, double b);

// Returns a * b
static DECLDIR double Multiply(double a, double b);

// Returns a / b
// Throws DivideByZeroException if b is 0
static DECLDIR double Divide(double a, double b);
};
}
DECLDIR double test(double , double ) ;

#ifdef __cplusplus
}
#endif


فایل .cpp :


// MathFuncsDll.cpp
// compile with: /EHsc /LD


#include "MathFuncsDll.h"

#include <stdexcept>
#define DLL_EXPORT

using namespace std;

#ifdef __cplusplus
extern "C" {
#endif

namespace MathFuncs
{
double MyMathFuncs::Add(double a, double b)
{
return a + b;
}

double MyMathFuncs::Subtract(double a, double b)
{
return a - b;
}

double MyMathFuncs::Multiply(double a, double b)
{
return a * b;
}

double MyMathFuncs::Divide(double a, double b)
{
if (b == 0)
{
throw new invalid_argument("b cannot be zero!");
}

return a / b;
}
}
double test(double a, double b)
{
return a+b;
}

#ifdef __cplusplus
}
#endif

دمت گرم

r00tkit
جمعه 04 شهریور 1390, 12:29 عصر
در مورد سوال اول ببین ما برای اینکه بتونیم از یه dll استفاده بود باید Prototype ان رو داشته باشیم خوب یه بار یه فایل .h می سازیم وبا یه #if بررسی می کنیم ایا می خوایم از header توی dll استفاده کنیم یا exe اگه dll بود یه DLL_EXPORT تعریف می کنیم

این جوری DLL_EXPORT #define

اگه exe بود تعریف نمی کنیم با این چیز ها که بهش می گن preprocessor ما خلاصه سازی می کنیم


سوال3 : جواب :
Let's start with the easy stuff: getting delay-load DLLs to work. First, you create a DLL just as you normally would. You also create an executable as you normally would, but you do have to change a couple of linker switches and relink the executable. Here are the two linker switches you need to add:

/Lib:DelayImp.lib

/DelayLoad:MyDll.dll

Warning The /DELAYLOAD and /DELAY linker switches cannot be set within your source code through #pragma comment(linker, ""). You need to set these two linker switches through the project properties.



یعنی چی ؟ یعنی لازم نیست کار خاصی توی dll انجام بدی فقط این linker option ها رو اضافه کن و دوباره برنامت رو لینک کن ( منبع windows via c/c++ )



سوال 4 ) ببین dll یه چیز ساده هستش ولی نکات زیادی داره به عبارتی خیلی نکات داره که مربوط می شه به PE

توصیه مهم : اگه دوست داری برنامه نویسی رو خوب یاد بگیری و یا شغلت برنامه نویسی باشه بهتره زبان اصلی بخونی

سوالت 3 رو فردا جواب می دم الان توی استراحتم

djsohrab2007
شنبه 05 شهریور 1390, 01:14 صبح
سلام
ممنون از زحمتی که کشیدی ، راستش از این چیزهایی که نوشتی بازم سوال دارم ولی روم نمیشه بپرسم، صبر می کنم زحمت سوال 2 را بکشی بعد اگر گفتی اشکال نداره بازم سوال می پرسم

ممنون که وقت گذاشتی دوست عزیز.

djsohrab2007
شنبه 05 شهریور 1390, 17:19 عصر
سلام،
من برای همین سوال 2 یک راه حل پیدا کردم ، ولی نمی دونم چرا به دلم نمی چسبه، اینجا می نویسمش ببین نظر تو چیه ؟ راه حل دیگه ای داره ؟ راه خوردت چیه ؟ و پیشنهادت ؟
من اینجا فقط برای تابع Add را می نویسم ، بقیش هم مثل همینه

ببین dll که در بالا کدش را گذاشتم به نام MathFuncsDll.dll است که در درایو D من ذخیره شده، با استفاده از
Microsoft Visual Studio Command Prompt و اجرای دستور زیر ، اسم توابع را بدست آوردم
C:\program Files (x86)\Microsoft visual studio 10.0\VC\bin>dumpbin.exe /exports D:\\MathFuncs.dll

که خروجی این دستور شد شکل زیر :

74467

یعنی با توجه به شکل اسم تابع Add شده : ?Add@MyMathFuncs@MathFuncs@@SANNN@Z

بعدش کد زیر :

#include<iostream>
#include<assert.h>
#include<Windows.h>

using namespace std;
typedef double (*testFuncs)(double,double) ;
int main()
{
HINSTANCE dllHandle = LoadLibrary(TEXT("D:\\MathFuncsDLL.dll"));
assert(dllHandle); // Exit( 0 ) if dllHandle == NULL.
FARPROC Add = GetProcAddress(dllHandle,"?Add@MyMathFuncs@MathFuncs@@SANNN@Z");
assert(Add);
testFuncs _Add = (testFuncs)(Add) ;
assert(_Add);
cout<<_Add(4,6);
system("pause");
return 0 ;

}

خوب از روی اسم تابع Add یعنی ?Add@MyMathFuncs@MathFuncs@@SANNN@Z یک خورده از فورمت نام گذاریش معلومه :
؟اسم تابع @اسم کلاس@اسم زیر فضا @@ بقیه اش را نمی دونم چه جوری نوشته

یعنی اگر ما نخواهیم از دستور dumpbin استفاده کنیم و فقط طریقه ی تعریف تابع را بدونیم چه جوری می توانیم اسم تابع را خودمان به این صورت بنویسیم و حالا برعکس اگر همچین اسمی به ما دادند چه طوری می توانیم بفهمیم که پروتوتایپ تابع به چه صورت است ؟

توی این دنیای برنامه نویسی هر چقدر هم موضوع ریز باشه ، سوال زیاده !!!

djsohrab2007
یک شنبه 06 شهریور 1390, 00:30 صبح
سلام، آقای geek1982 (http://barnamenevis.org/member.php?113200-geek1982) ، قرار بود امروز جواب بدی پس چی شد ؟ من از صبح هی این صفحه را باز کردم و منتظر شما !

راستی من سیستم نام گذاریش را متوجه شدم :

به شرطی که توابع داخل کلاس تعریف شده باشند یعنی متد باشند داریم :

static = SA
non-static = QAE
int = H
double = N
char = D
void = X
پایان هم اگر تابع ورودی داشته باشه @Z و اگر نداشته باشه Z ترتیب هم به صورت زیر است :
<static or non-static,type of return , types of inputs <
منبع : خودم هی تابع نوشتم و حالت های مختلف را نگاه کردم