ارتباط لوا و #c با استفاده از ++c

the_king

مدیرکل انجمن
ممنون
فایل def چیه؟
الان وقتی بدنه ی این تابع رو طبق دستوری که دادید ، نوشتم ، بعدش از منوی build گزینه ی build solution رو بزنم مگه کافی نیست؟ و بعدش هم از فایل dll ای که ساخته شد استفاده کنم؟!

کدی که داخل برنامه می نویسید مریوط به مرحله Compile ئه، اون فایل def یک راهنما است برای مرحله لینک کردن که بعد از کامپایل توسط لینکر انجام میشه و اونجا باید تصمیم بگیره که از داخل برنامه چه توابعی
به بیرون کتابخانه راه داشته باشند.
لینک آموزش نحوه export کردن تابع از ++C خواسته بودید که دادم، اگه مطالعه می کردید در مورد اون def و کاربردش نوشته شده بود.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
کدی که داخل برنامه می نویسید مریوط به مرحله Compile ئه، اون فایل def یک راهنما است برای مرحله لینک کردن که بعد از کامپایل توسط لینکر انجام میشه و اونجا باید تصمیم بگیره که از داخل برنامه چه توابعی
به بیرون کتابخانه راه داشته باشند.
لینک آموزش نحوه export کردن تابع از ++C خواسته بودید که دادم، اگه مطالعه می کردید در مورد اون def و کاربردش نوشته شده بود.

ممنون آقا علی
الان طبق چیزی که اینجا گفتید :

http://forum.majidonline.com/threads/177816-dll-به-زبان-C?p=1162858&viewfull=1#post1162858

فقط باید جداگانه خودم در پوشه ای که dll تولید میشه (bin\debug) یه فایل ای با پسوند def ایجاد کنم با ساختار :

کد:
LIBRARY YourLibraryName
EXPORTS
    CompareInt

که گفتید (نام تابع و ... که توضیح دادید رو میدونم که باید بجا CompareInt در بالا نوشته شه و ...)
و بعدش هم فایل dll مو بسازم دیگه

----------------
خوب حالا این فایل def همرای فایل dll همیشه باید باشه دیگه؟
آخه من تا حالا هر جا فایل dll دیدم که برای اتوپلی ساخته شده ، یک فایل dll بیشتر نبود و فایل های دیگه مثل def و اینا هیچ وقت همراش نبودن!! پس اونا از چه ساختار یا قضیه ای استفاده کردن؟ یا همین فایلی که شما برام درست کردین چرا این فایل def رو نداره پس؟

----------------
آها ببخشید .منظورتون از قسمت solution explorer هست که Add Files To Folder رو میزنیم؟ :

http://forum.majidonline.com/thread...ه-از-ان-در-c?p=1209678&viewfull=1#post1209678

یعنی از این قسمت آبی شده؟ :

sjpn6ue90um3.jpg



ولی وقتی روی source file کلیک راست میکنم ، گزینه ی Add Files To Folder نداره. ویژال استودیوی من نسخه 2015 هست
 
آخرین ویرایش:

the_king

مدیرکل انجمن

ممنون آقا علی
الان طبق چیزی که اینجا گفتید :

http://forum.majidonline.com/threads/177816-dll-به-زبان-C?p=1162858&viewfull=1#post1162858

فقط باید جداگانه خودم در پوشه ای که dll تولید میشه (bin\debug) یه فایل ای با پسوند def ایجاد کنم با ساختار :

کد:
LIBRARY YourLibraryName
EXPORTS
    CompareInt

که گفتید (نام تابع و ... که توضیح دادید رو میدونم که باید بجا CompareInt در بالا نوشته شه و ...)
و بعدش هم فایل dll مو بسازم دیگه

----------------
خوب حالا این فایل def همرای فایل dll همیشه باید باشه دیگه؟
آخه من تا حالا هر جا فایل dll دیدم که برای اتوپلی ساخته شده ، یک فایل dll بیشتر نبود و فایل های دیگه مثل def و اینا هیچ وقت همراش نبودن!! پس اونا از چه ساختار یا قضیه ای استفاده کردن؟ یا همین فایلی که شما برام درست کردین چرا این فایل def رو نداره پس؟

----------------
آها ببخشید .منظورتون از قسمت solution explorer هست که Add Files To Folder رو میزنیم؟ :

http://forum.majidonline.com/thread...ه-از-ان-در-c?p=1209678&viewfull=1#post1209678

یعنی از این قسمت آبی شده؟ :

sjpn6ue90um3.jpg



ولی وقتی روی source file کلیک راست میکنم ، گزینه ی Add Files To Folder نداره. ویژال استودیوی من نسخه 2015 هست

اون فایل def رو Linker می خونه که فایل dll رو بعد از کامپایل می سازه، بودنش ربطی به بعد از ساختن فایل dll نداره که کنارش باشه یا نباشه. هیچوقت کنار dll فایل def قرار نمی دهند.
روی Source Files راست کلیک کنید و Add > New Item رو انتخاب کنید. (Module-Definition File (.def جزو گروه Code ها است، صرفا اسم فایل رو برای سازگاری MyTestCPPCLR.def قرار بدهید که با فایل cpp
و نام پروژه تون مطابقت داشته باشه. بعد همون سطر ها رو ویژوال استدیو داخلش می نویسه، فقط باید اسم تابع تون رو اضافه کنید.
دقت کنید که هر پروژه فقط می تونه یک فایل def داشته باشه، بخواهید دومی رو اضافه کنید ایراد می گیره.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اون فایل def رو Linker می خونه که فایل dll رو بعد از کامپایل می سازه، بودنش ربطی به بعد از ساختن فایل dll نداره که کنارش باشه یا نباشه. هیچوقت کنار dll فایل def قرار نمی دهند.
روی Source Files راست کلیک کنید و Add > New Item رو انتخاب کنید. (Module-Definition File (.def جزو گروه Code ها است، صرفا اسم فایل رو برای سازگاری MyTestCPPCLR.def قرار بدهید که با فایل cpp
و نام پروژه تون مطابقت داشته باشه. بعد همون سطر ها رو ویژوال استدیو داخلش می نویسه، فقط باید اسم تابع تون رو اضافه کنید.
دقت کنید که هر پروژه فقط می تونه یک فایل def داشته باشه، بخواهید دومی رو اضافه کنید ایراد می گیره.

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

----------------------------

حالا اگه نشد بین سی شارپ و سی پلاس
پلاس و لوا راهی ایجاد کنیم ، پس بهم میگین اگه اللان توی همین پروژه ای که نوشتم ، بخوام از فضای نام و متدهای یک کلاس استفاده کنم (فرض کنید از system.directiory.delete و هر متد دیگه از کلاس و فضای نام) ، باید چی کار کنم؟ آخه اینجا الان نمیزاره که از فضای نام و کلاس یا متد اون کلاس استتفاده کنم (فکر کنم بخاطر اینه که بصورت تابعی نوشتم و از کلاس استفاده نکردم ، باشه . از اون طرف هم اگه بصورت کلاس بنویسم که توی اتوپلی نمیشه فراخونی کرد)

---------------------------

یه سئوال دیگه اینکه میتونم توی زبان ویژال بیسیک همچین dll ای طراحی کنم که بصورت تابعی بشه خروجی گرفت (نه بصورت کلاس) تا در اتوپلی ساپورت بشه ؟

 
آخرین ویرایش:

the_king

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

----------------------------

حالا اگه نشد بین سی شارپ و سی پلاس
پلاس و لوا راهی ایجاد کنیم ، پس بهم میگین اگه اللان توی همین پروژه ای که نوشتم ، بخوام از فضای نام و متدهای یک کلاس استفاده کنم (فرض کنید از system.directiory.delete و هر متد دیگه از کلاس و فضای نام) ، باید چی کار کنم؟ آخه اینجا الان نمیزاره که از فضای نام و کلاس یا متد اون کلاس استتفاده کنم (فکر کنم بخاطر اینه که بصورت تابعی نوشتم و از کلاس استفاده نکردم ، باشه . از اون طرف هم اگه بصورت کلاس بنویسم که توی اتوپلی نمیشه فراخونی کرد)

---------------------------

یه سئوال دیگه اینکه میتونم توی زبان ویژال بیسیک همچین dll ای طراحی کنم که بصورت تابعی بشه خروجی گرفت (نه بصورت کلاس) تا در اتوپلی ساپورت بشه ؟

تنها کامپایلر Net. که این تنظیمات Export رو داره ++C ئه، Visual Basic و #C شرایط شون یکسانه.

کد:
		String^ s = "C:\\New Folder";
		System::IO::Directory::Delete(s);
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
تنها کامپایلر Net. که این تنظیمات Export رو داره ++C ئه، Visual Basic و #C شرایط شون یکسانه.

کد:
        String^ s = "C:\\New Folder";
        System::IO::Directory::Delete(s);

ممنون آقا علی
یعنی توی این حالت اولا با using نمیشه فضای نام رو شامل کرد و دوما بجای گذاشتن یک نقطه (برای دسترسی به اعضای یک فضای نام و کلاس و ...) باید از علامت دو نقل قول یعنی از علامت :: استفاده کنیم؟
الان مشکل سی شارپ که توی ++C درست کردید نمیدونید چیه؟
 

the_king

مدیرکل انجمن

ممنون آقا علی
یعنی توی این حالت اولا با using نمیشه فضای نام رو شامل کرد و دوما بجای گذاشتن یک نقطه (برای دسترسی به اعضای یک فضای نام و کلاس و ...) باید از علامت دو نقل قول یعنی از علامت :: استفاده کنیم؟
الان مشکل سی شارپ که توی ++C درست کردید نمیدونید چیه؟
چرا نشه، فایل هدر h. پروژه تون رو ببینید، همون بالا سطر های using namespace رو نمی بینید؟ برای موارد static بله، ولی برای اعضاء یک شیء <- قرار می گیره.
کد:
		String^ s = "C:\\New Folder";
		s = s->Replace("New","Old");

کد:
using namespace System;
using namespace System::Runtime::InteropServices;
نه dll سی شارپ مشکل داره و نه dll ئه ++C، اگه مشکلی داشت توابع توی ویژوال بیسیک کلاسیک اجرا نمیشدند. مشکل از فراخوانی شما است، احتمالا رشته ها String رو Unicode به توابع نمی فرستید و یا نوع داده عددی تون 32 بیتی نیست.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
چرا نشه، فایل هدر h. پروژه تون رو ببینید، همون بالا سطر های using namespace رو نمی بینید؟ برای موارد static بله، ولی برای اعضاء یک شیء <- قرار می گیره.
کد:
        String^ s = "C:\\New Folder";
        s = s->Replace("New","Old");

کد:
using namespace System;
using namespace System::Runtime::InteropServices;

ممنون
مگه توی ++C میشه رشته تعریف کرد؟! آخه تا جایی که میدونستم توی ++C آرایه ای از کاراکتر میشد تعریف کرد که به عنوان رشته بکار بره!!
بعد از String علامت ^ چیه؟
قضیه ی علامت <- برای اعضای غیر static رو متوجه نشدم که کی و کجای ایجاد شی باید بکار بره

نه dll سی شارپ مشکل داره و نه dll ئه ++C، اگه مشکلی داشت توابع توی ویژوال بیسیک کلاسیک اجرا نمیشدند. مشکل از فراخوانی شما است، احتمالا رشته ها String رو Unicode به توابع نمی فرستید و یا نوع داده عددی تون 32 بیتی نیست.

منظورمو بد متوجه شدین . یعنی من بد گفتم که عذر میخوام و منظورم این نبود که مشکل از شما یا بیسیک یا سی پلاس پلاس یا ... هست
اتوپلی یونیکد رو بصورت رسمی ساپورت نمیکنه . حالا بماند
ممنون
 

the_king

مدیرکل انجمن
ممنون
مگه توی ++C میشه رشته تعریف کرد؟! آخه تا جایی که میدونستم توی ++C آرایه ای از کاراکتر میشد تعریف کرد که به عنوان رشته بکار بره!!
بعد از String علامت ^ چیه؟
قضیه ی علامت <- برای اعضای غیر static رو متوجه نشدم که کی و کجای ایجاد شی باید بکار بره



منظورمو بد متوجه شدین . یعنی من بد گفتم که عذر میخوام و منظورم این نبود که مشکل از شما یا بیسیک یا سی پلاس پلاس یا ... هست
اتوپلی یونیکد رو بصورت رسمی ساپورت نمیکنه . حالا بماند
ممنون
++C که خودش یک کلاس string داشت که برای تعریف کردن رشته بصورت یک شیء بود، پیاده سازی اش در هر کامپایلری تا حدی متفاوت بود و البته ارتباطی با آنچیزی که به نام String در NET. هست
نداره، C++ CLR زبان خاصی است که به کتابخانه NET Framework دسترسی داره و تمامی مواردی که در NET Framework. هست در C++ CLR وجود داره که شامل System.String هم میشه.
طبق سنت قدیمی در ++C اشاره گر ها رو با * تعریف می کنند و با & برای پارامتر ها رفرنس تعریف می کنند و یا آدرس حافظه متغیر ها رو بدست میارند.
اصولا موقع کار با اشیاء هم باید آدرس حافظه شیء در یک متغیر از نوع اشاره گر قرار بگیره. اما این * برای اشاره گر هایی طراحی شده که مدیریت حافظه شون با برنامه نویسه، یعنی هر وقت لازم دیدید باید
خودتون با کد حافظه بهش تخصیص بدهید و هر زمانی که لازمش نداشتید حافظه اش را آزاد کنید.

در حالی که در NET. کلا مدیریت حافظه با برنامه نویس نیست و زبان برای اینکار garbage collector داره و بصورت خودکار حافظه رو مدیریت می کنه.
به همین جهت در C++ CLR استفاده از * برای دسترسی به اشیاء NET. و اعضاء اون مناسب نیست، برای همین در C++ CLR برای تعریف اشاره گر به اشیاء از ^ استفاده می کنند که نوعی اشاره گر هست ولی
به نام handler شناخته میشه، نه pointer و مدیریت حافظه اش هم با برنامه نویس نیست و خودکار ئه.
موقع ساختن شیء هم از gcnew استفاده میشه. شیء رو شما در موقعی که خواستید و لازمش داشتید ایجاد می کنید و برای دسترسی به اعضاء اش هم باید از <- استفاده کنید.
کلا <- برای دسترسی به اعضاء یک شیء ای بکار میره که اشاره گر اش رو دارید، هر عضوی که با اشاره گر بهش دسترسی پیدا می کنید <- لازم داره.
کد:
	class Test
	{
		public:
			int X;
	};
کد:
	Test t;
	t.X = 2;
	Test *a = &t;
	a->X = 6;
	int m = t.X;
برای دسترسی به t.X از نقطه استفاده شد چون t اشاره گر نیست، ولی a اشاره گری به t است و برای همین a->X نوشته شد.
m برابر 6 خواهد شد، چون a به t اشاره می کند و a->X دارد t.X را تغییر می دهد.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون آقا علی
میگم آموزش زبان visual studio C++ CLR جایی نیست؟ pdf ای چیزی؟ (زبان فارسی)
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
آقا علی ، من وقتی توی #C یه dll ای بصورت Unmanaged Export مینویسم که توش چند تا کلاس (که توی هر کلاس یک متد) یا یک کلاسی که چند متد توش نوشته شده ، موقع اجرا شدن ، سالم اجرا میشه ولی فایل dll رو use file قرار میده و نمیشه حذف کرد (حتی بعد از بستن پروژه ی اتوران) و هم اینکه بعد از بستن پروژه ی اتوران ، ظاهرا پروژه بسته میشه ولی در پروسه ، میمونه و مقدار 20 درصد از پردازنده رو (حتی بعد از بستن) مشغول میکنه
البته همیشه در حالت چند متدی این مشکل وجود نداره (50 درصد موقع اجرا این مشکل هست)
ولی با تک متد مشکلی نداره انگار
مشکل اتوپلی (تابع ای که باعث فراخونی dll میشه) هست. درسته؟
 

the_king

مدیرکل انجمن
آقا علی ، من وقتی توی #C یه dll ای بصورت Unmanaged Export مینویسم که توش چند تا کلاس (که توی هر کلاس یک متد) یا یک کلاسی که چند متد توش نوشته شده ، موقع اجرا شدن ، سالم اجرا میشه ولی فایل dll رو use file قرار میده و نمیشه حذف کرد (حتی بعد از بستن پروژه ی اتوران) و هم اینکه بعد از بستن پروژه ی اتوران ، ظاهرا پروژه بسته میشه ولی در پروسه ، میمونه و مقدار 20 درصد از پردازنده رو (حتی بعد از بستن) مشغول میکنه
البته همیشه در حالت چند متدی این مشکل وجود نداره (50 درصد موقع اجرا این مشکل هست)
ولی با تک متد مشکلی نداره انگار
مشکل اتوپلی (تابع ای که باعث فراخونی dll میشه) هست. درسته؟
نمیشه گفت مشکل، DLL اصولا برای استفاده اشتراکی طراحی شد، یعنی چند برنامه بتوانند همزمان ازش استفاده کنند، به همین جهت سیستم در آزاد کردن حافظه اش عجله نمی کنه.
روال اینطوریه که وقتی اولین برنامه درخواست دسترسی به کتابخانه رو داد سیستم عامل کتابخانه رو Load می کنه و در حافظه سیستم برایش فضا در نظر می گیره
مادامی که برنامه ای در حال اجرا است که درخواست فراخوانی این کتابخانه رو داره از داخل حافظه آزاد اش نمی کنه.
زمانی که آخرین برنامه متقاضی هم بسته شد باز یه مدت زمانی که به مدیریت حافظه سیستم بستگی داره همچنان DLL رو در حافظه نگه میداره، مگر اینکه از لحاظ حافظه آزاد خیلی در مضیقه باشه.
دو تا کار می توانید انجام بدید.

اولا ویندوز یه تنظیمی داره که اگه تغییر اش بدید در اون ویندوز DLL ها به محض تموم شدن کارشون از حافظه در میان و باقی نمی مونند.
در مسیر HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer در Registry ویندوز اگه یه متغیر String با نام AlwaysUnloadDLL قرار بگیره که مقدار 1 داخلش ذخیره بشه، دیگه سیستم DLL رو در حافظه بلا استفاده نگه نمیداره. برای تاثیر گذاشتن این تنظیم یکبار Restart کردن سیستم لازمه.

ثانیا می توانید از API ویندوز CoFreeUnusedLibrariesEx رو که در Ole32.dll قرار داره فراخوانی کنید تا تمامی DLL های بلا استفاده آزاد بشن.
MSDN - CoFreeUnusedLibrariesEx function
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
نمیشه گفت مشکل، DLL اصولا برای استفاده اشتراکی طراحی شد، یعنی چند برنامه بتوانند همزمان ازش استفاده کنند، به همین جهت سیستم در آزاد کردن حافظه اش عجله نمی کنه.
روال اینطوریه که وقتی اولین برنامه درخواست دسترسی به کتابخانه رو داد سیستم عامل کتابخانه رو Load می کنه و در حافظه سیستم برایش فضا در نظر می گیره
مادامی که برنامه ای در حال اجرا است که درخواست فراخوانی این کتابخانه رو داره از داخل حافظه آزاد اش نمی کنه.
زمانی که آخرین برنامه متقاضی هم بسته شد باز یه مدت زمانی که به مدیریت حافظه سیستم بستگی داره همچنان DLL رو در حافظه نگه میداره، مگر اینکه از لحاظ حافظه آزاد خیلی در مضیقه باشه.
دو تا کار می توانید انجام بدید.

اولا ویندوز یه تنظیمی داره که اگه تغییر اش بدید در اون ویندوز DLL ها به محض تموم شدن کارشون از حافظه در میان و باقی نمی مونند.
در مسیر HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer در Registry ویندوز اگه یه متغیر String با نام AlwaysUnloadDLL قرار بگیره که مقدار 1 داخلش ذخیره بشه، دیگه سیستم DLL رو در حافظه بلا استفاده نگه نمیداره. برای تاثیر گذاشتن این تنظیم یکبار Restart کردن سیستم لازمه.

ثانیا می توانید از API ویندوز CoFreeUnusedLibrariesEx رو که در Ole32.dll قرار داره فراخوانی کنید تا تمامی DLL های بلا استفاده آزاد بشن.
MSDN - CoFreeUnusedLibrariesEx function

سلام
ممنون استاد علی
میگم من آخر نفهمیدم دقیقا کی این قضیه ی using فایل های dll رخ میده
توی آموزش اتوپلی ، قسمت 50 ، همچین اتفاقی افتاده بود ولی الان دقیقا همون صحنه رو شبیه سازی میکنم (همون متدها و ...) ولی اصلا مشکل using فایل های dll رخ نمیده ! چندین بار هم تست میکنم ولی بدون مشکل (using) کار میکنه
نمیدونین دقیقا چه زمانی این مشکل پیش میاد؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
استاد علی ، من یه چیزی رو متوجه نشدم
البته به لوا مربوط بشه احتمالا . گفتم شاید بدونین ، بپرسم
اینکه من نمیتونم آرایه رو از لوا به متدهایی که در سی شارپ مینویسم (dll) ، بفرستم و نه دریافت کنم
شما دلیل اش رو نمیدونین چیه؟
البته شدن میشه . یعنی بچه ها که dll درست میکنن (حالا زبانش رو نمیدونم) ، میشه آرایه ارسال کرد
 

the_king

مدیرکل انجمن
سلام
ممنون استاد علی
میگم من آخر نفهمیدم دقیقا کی این قضیه ی using فایل های dll رخ میده
توی آموزش اتوپلی ، قسمت 50 ، همچین اتفاقی افتاده بود ولی الان دقیقا همون صحنه رو شبیه سازی میکنم (همون متدها و ...) ولی اصلا مشکل using فایل های dll رخ نمیده ! چندین بار هم تست میکنم ولی بدون مشکل (using) کار میکنه
نمیدونین دقیقا چه زمانی این مشکل پیش میاد؟
منظورتون کلمه کلیدی using که نیست چون using namespace رو قاعدتا به دلیل کاربرد مشابهش در #C باید تا الان خوب شناخته باشید، using برای معرفی namespace های پیشفرض و در نتیجه خلاصه نویسی کد ئه.
شما هر فایلی رو در سیستم عامل به هر دلیلی بصورت باز نگه دارید در وضعیت using می مونه و اجازه تغییر نام، جابجایی، حذف و ... داده نمیشه. ممکنه پروسه ای که اون فایل رو باز نگه میداره Explorer یا ویروس کش یا حتی پروسه برنامه ای باشه که هنوز خاتمه نیافته. کتابخانه های DLL عمومی Unmanaged به هر حال چه مستقیم و چه غیر مستقیم با LoadLibrary یا LoadLibraryEx فراخوانی می شوند و با FreeLibrary یا FreeLibraryAndExitThread آزاد می شوند، اینها توابع API ویندوز اند و جزئی از Kernel32.dll. اگه تابع بخش آزاد سازی صورت نگیره، سیستم عامل فرض رو بر این میگیره که هنوز به dll نیاز ئه و نباید آزاد بشه.

استاد علی ، من یه چیزی رو متوجه نشدم
البته به لوا مربوط بشه احتمالا . گفتم شاید بدونین ، بپرسم
اینکه من نمیتونم آرایه رو از لوا به متدهایی که در سی شارپ مینویسم (dll) ، بفرستم و نه دریافت کنم
شما دلیل اش رو نمیدونین چیه؟
البته شدن میشه . یعنی بچه ها که dll درست میکنن (حالا زبانش رو نمیدونم) ، میشه آرایه ارسال کرد
آرایه Managed رو قطعا نمی توانید همونطوری به dll بفرستید، در نظر بگیرید که حتی در هر لحظه ممکنه آدرس حافظه ها در برنامه تون بصورت خودکار تغییر کنه و منجر به Crash بشه. یعنی اینکه همینطوری آدرس حافظه یک آرایه Managed رو به dll ارسال کنید به کل اشتباهه. کامپایلر فرضا در مورد نوع داده ساده ای مثل string بصورت خودکار داره Marshaling انجام میده که از چشم شما پنهانه، یعنی داده رو از حافظه Managed منتقل می کنه به یک حافظه Unmanaged که به garbage collector هم اجازه جابجایی اش داده نمیشه و برعکس. ولی برای همه انواع داده این کار رو بصورت خودکار انجام نمیده. شما باید خودتان با متد های System.Runtime.InteropServices.Marshal کار کنید. یعنی اول یک بخش حافظه به مقدار مناسب تخصیص بدید، اجازه جابجایی اش رو از gc بگیرید، با داده داخل اون آرایه پر اش کنید، آدرس حافظه رو به کتابخانه ارسال کنید. وقتی هم کار تون تموم شد باید حافظه اش رو آزاد کنید. یک مثال بزنید تا نشون بدم چطوری.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
منظورتون کلمه کلیدی using که نیست چون using namespace رو قاعدتا به دلیل کاربرد مشابهش در #C باید تا الان خوب شناخته باشید، using برای معرفی namespace های پیشفرض و در نتیجه خلاصه نویسی کد ئه.
شما هر فایلی رو در سیستم عامل به هر دلیلی بصورت باز نگه دارید در وضعیت using می مونه و اجازه تغییر نام، جابجایی، حذف و ... داده نمیشه. ممکنه پروسه ای که اون فایل رو باز نگه میداره Explorer یا ویروس کش یا حتی پروسه برنامه ای باشه که هنوز خاتمه نیافته. کتابخانه های DLL عمومی Unmanaged به هر حال چه مستقیم و چه غیر مستقیم با LoadLibrary یا LoadLibraryEx فراخوانی می شوند و با FreeLibrary یا FreeLibraryAndExitThread آزاد می شوند، اینها توابع API ویندوز اند و جزئی از Kernel32.dll. اگه تابع بخش آزاد سازی صورت نگیره، سیستم عامل فرض رو بر این میگیره که هنوز به dll نیاز ئه و نباید آزاد بشه.

ممنون استاد علی
نه . اون using نه :green:
منظورم از using فایل ، همون موقع حذف dll (بعد از بستن برنامه ای که از اون dll استفاده میکرد) هست که در 5 پست بالاتر گفتم و شما در 4 پست بالاتر توضیح داده بودین
پیام سیستم عامل موقع حذف فایل منظورمه
حالا فعلا مهم نیست چندان چون متد فراخونی کننده ی dll رو عوض کردم و فکر کنم با این مشکلی پیش نیاد و خودش بعد از استفاده ، احتمالا میبنده


آرایه Managed رو قطعا نمی توانید همونطوری به dll بفرستید، در نظر بگیرید که حتی در هر لحظه ممکنه آدرس حافظه ها در برنامه تون بصورت خودکار تغییر کنه و منجر به Crash بشه. یعنی اینکه همینطوری آدرس حافظه یک آرایه Managed رو به dll ارسال کنید به کل اشتباهه. کامپایلر فرضا در مورد نوع داده ساده ای مثل string بصورت خودکار داره Marshaling انجام میده که از چشم شما پنهانه، یعنی داده رو از حافظه Managed منتقل می کنه به یک حافظه Unmanaged که به garbage collector هم اجازه جابجایی اش داده نمیشه و برعکس. ولی برای همه انواع داده این کار رو بصورت خودکار انجام نمیده. شما باید خودتان با متد های System.Runtime.InteropServices.Marshal کار کنید. یعنی اول یک بخش حافظه به مقدار مناسب تخصیص بدید، اجازه جابجایی اش رو از gc بگیرید، با داده داخل اون آرایه پر اش کنید، آدرس حافظه رو به کتابخانه ارسال کنید. وقتی هم کار تون تموم شد باید حافظه اش رو آزاد کنید. یک مثال بزنید تا نشون بدم چطوری.

مثلا در dll ای که کد زیر رو در سی شارپ داره :

کد:
namespace ClassLibrary2
{
    public class Class2
    {
        [DllExport("ArrayFunc", CallingConvention.StdCall)]
        public static void ArrayFunc(int[] myPar)
        {
           
        }

    }
}

که یک متد خالی هست و فقط یک آرایه ای از اعداد رو دریافت میکنه رو میخوام توی اتوپلی فراخونی کنم که کدش در زیر هست :

کد:
dllPath = _SourceFolder.."\\ClassLibrary2.dll";
dllHdl = Library.Load(dllPath);
if (dllHdl ~= nil) then
myIntArray = {10, 30, 513};
dllHdl.ArrayFunc( myIntArray );
dllHdl:Close_();
end

ارور میده و بررنامه کرش میشه
توضیحات کد لوا در بالا اینه که خط اول ، مسیر و آدرس فایل dll ای که در سی شارپ نوشته شد هست
خط 2 ، باعث لود dll میشه
خط 3 ، چک میکنه اگه dll لود شد و اروری نداشت (مخالف nil که همون null در سی شارپ هست ، شد) ادامه ی کد رو اجرا کنه
خط 4 ، یه آرایه در لوا ساخته شد . البته آرایه در لوا ، مثل آرایه در سی شارپ و ... نیست که فقط بشه آرایه از یه نوع خواص ساخت . یعنی میشه اعداد و رشته و ... رو بصورت ادغام در یک آرایه ریخت . تقریبا شبیه object ها در سی شارپ میمونه . توی این مثال که من همه رو اعداد گرفتم . حالا نمیدونم بخاطر خاصیت آرایه ها در لوا (که میشه انواع مختلف داده ها رو توی آرایه اش ریخت) هست که باعث ارور موقع ارسال به سی شارپ میشه یا نه !
خط 5 هم متد ArrayFunc ای که در سی شارپ درست کردیم رو فراخونی میکنه
خط 6 هم بعد از استفاده ، فایل dll رو میبنده
 

the_king

مدیرکل انجمن
ممنون استاد علی
نه . اون using نه :green:
منظورم از using فایل ، همون موقع حذف dll (بعد از بستن برنامه ای که از اون dll استفاده میکرد) هست که در 5 پست بالاتر گفتم و شما در 4 پست بالاتر توضیح داده بودین
پیام سیستم عامل موقع حذف فایل منظورمه
حالا فعلا مهم نیست چندان چون متد فراخونی کننده ی dll رو عوض کردم و فکر کنم با این مشکلی پیش نیاد و خودش بعد از استفاده ، احتمالا میبنده




مثلا در dll ای که کد زیر رو در سی شارپ داره :

کد:
namespace ClassLibrary2
{
    public class Class2
    {
        [DllExport("ArrayFunc", CallingConvention.StdCall)]
        public static void ArrayFunc(int[] myPar)
        {
          
        }

    }
}

که یک متد خالی هست و فقط یک آرایه ای از اعداد رو دریافت میکنه رو میخوام توی اتوپلی فراخونی کنم که کدش در زیر هست :

کد:
dllPath = _SourceFolder.."\\ClassLibrary2.dll";
dllHdl = Library.Load(dllPath);
if (dllHdl ~= nil) then
myIntArray = {10, 30, 513};
dllHdl.ArrayFunc( myIntArray );
dllHdl:Close_();
end

ارور میده و بررنامه کرش میشه
توضیحات کد لوا در بالا اینه که خط اول ، مسیر و آدرس فایل dll ای که در سی شارپ نوشته شد هست
خط 2 ، باعث لود dll میشه
خط 3 ، چک میکنه اگه dll لود شد و اروری نداشت (مخالف nil که همون null در سی شارپ هست ، شد) ادامه ی کد رو اجرا کنه
خط 4 ، یه آرایه در لوا ساخته شد . البته آرایه در لوا ، مثل آرایه در سی شارپ و ... نیست که فقط بشه آرایه از یه نوع خواص ساخت . یعنی میشه اعداد و رشته و ... رو بصورت ادغام در یک آرایه ریخت . تقریبا شبیه object ها در سی شارپ میمونه . توی این مثال که من همه رو اعداد گرفتم . حالا نمیدونم بخاطر خاصیت آرایه ها در لوا (که میشه انواع مختلف داده ها رو توی آرایه اش ریخت) هست که باعث ارور موقع ارسال به سی شارپ میشه یا نه !
خط 5 هم متد ArrayFunc ای که در سی شارپ درست کردیم رو فراخونی میکنه
خط 6 هم بعد از استفاده ، فایل dll رو میبنده
من هم نمی دونم اون myIntArray با چه منطقی باید معادل []int باشه :green:. احتمال داره دقیقا با هیچکدوم از انواع داده ای عمومی در #C معادل نباشه.
وقتی فقط می خواهید داده را بخوانید :
کد:
        public static void ArrayFunc(IntPtr ptr)
        {
            var myPar = new int[3];
            Marshal.Copy(ptr, myPar, 0, 3);
        }

و وقتی می خواهید تغییرش هم بدهید :
کد:
        public static void ArrayFunc(IntPtr ptr)
        {
            var myPar = new int[3];
            Marshal.Copy(ptr, myPar, 0, 3);
            .
            .
            .
            Marshal.Copy(myPar, 0, ptr, 3);
        }
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
من هم نمی دونم اون myIntArray با چه منطقی باید معادل []int باشه :green:. احتمال داره دقیقا با هیچکدوم از انواع داده ای عمومی در #C معادل نباشه.
وقتی فقط می خواهید داده را بخوانید :
کد:
        public static void ArrayFunc(IntPtr ptr)
        {
            var myPar = new int[3];
            Marshal.Copy(ptr, myPar, 0, 3);
        }

و وقتی می خواهید تغییرش هم بدهید :
کد:
        public static void ArrayFunc(IntPtr ptr)
        {
            var myPar = new int[3];
            Marshal.Copy(ptr, myPar, 0, 3);
            .
            .
            .
            Marshal.Copy(myPar, 0, ptr, 3);
        }

ممنون استاد علی
حالا من اسم آرایه رو اغماض کردم :green: البته آرایه در لوا ، بجای اینکه عملکرد شبیه object رو در سی شارپ داشته باشه ، دقیقا عملکرد کلاس dynamic ها رو در سی شارپ داره . چون در زمان اجرا چک میشه . البته همه چیز در لوا در زمان اجرا چک میشه و کلا زبان مفسری هست . همینجا هم خواستم یه مسئله ای که به نظرم برای کسایی که با زبان های اسکریپتی به غلط جا افتاد رو ازتون بپرسم که صحیح هست یا غلط و اونم اینه که مرسوم هست که میگن "دیکمپایلر اتوپلی" . خوب اتوپلی که از خودش چیزی نداره و از زبان لوا استفاده میکنه . لوا هم که تا جایی که من میدونم اصلا کمپایلر نداره و زمان اجرا همه چی رو چک میکنه و مفسری هست . پس این اصطلاح باید غلط باشه دیگه . درسته؟ یعنی در واقع باید اسمش باشه "دیمفسر :green: اتوپلی" . بعد اینکه من نفهمیدم این اساتیدهایی که با لوا و اتوپلی کار میکنن ، کلا چجوری و با چه زبان برنامه نویسی ای دیکمپایلر اتوپلی رو درست میکنن و کلا مباحث هک و دیکمپایلر درست کردن و ایناها ، چجوری هست و نیاز به چه علوم هایی داره؟ شما میدونین؟
------------------
آها منظورتون اینه که بجای اینکه آرایه رو بصورت مستقیم از لوا بفرستم به سی شارپ ، بجاش آدرس اشاره گر اون آرایه رو از لوا بفرستم به سی شارپ و بعد با همین کلاس مارشال که گفتین ، اون اشاره گر رو (که Unmanaged بود) به آرایه ی Managed تبدیل کنم؟
اگه تعداد اعضای آرایه رو ندونم و هر بار که طرف فراخونی میکنه متفاوت باشه ، میشه بجای آرایه ی myPar که در بالا تعریف کردین ، از یه کلاس دینامیک مثل ArrayList و ... استفاده کنم تا راحت تر تعداد اعضاش رو متوجه شم؟
 

the_king

مدیرکل انجمن
ممنون استاد علی
حالا من اسم آرایه رو اغماض کردم :green: البته آرایه در لوا ، بجای اینکه عملکرد شبیه object رو در سی شارپ داشته باشه ، دقیقا عملکرد کلاس dynamic ها رو در سی شارپ داره . چون در زمان اجرا چک میشه . البته همه چیز در لوا در زمان اجرا چک میشه و کلا زبان مفسری هست . همینجا هم خواستم یه مسئله ای که به نظرم برای کسایی که با زبان های اسکریپتی به غلط جا افتاد رو ازتون بپرسم که صحیح هست یا غلط و اونم اینه که مرسوم هست که میگن "دیکمپایلر اتوپلی" . خوب اتوپلی که از خودش چیزی نداره و از زبان لوا استفاده میکنه . لوا هم که تا جایی که من میدونم اصلا کمپایلر نداره و زمان اجرا همه چی رو چک میکنه و مفسری هست . پس این اصطلاح باید غلط باشه دیگه . درسته؟ یعنی در واقع باید اسمش باشه "دیمفسر :green: اتوپلی" . بعد اینکه من نفهمیدم این اساتیدهایی که با لوا و اتوپلی کار میکنن ، کلا چجوری و با چه زبان برنامه نویسی ای دیکمپایلر اتوپلی رو درست میکنن و کلا مباحث هک و دیکمپایلر درست کردن و ایناها ، چجوری هست و نیاز به چه علوم هایی داره؟ شما میدونین؟
بستگی داره برای چه موضوعی بکارش می برند چون مرسوم ئه که برای خروجی نرم افزار هایی مثل اتوپلی Decompiler می سازند که مثلا خروجی اجرایی رو به پروژه اتوپلی بر می گردونه.
کارکرد کامپایلر اتوپلی مستقیما ارتباطی با لوا نداره، پروژه اتوپلی رو به فایل اجرایی تبدیل می کنه. اگه می گفتند دیکمپایلر لوا، خوب احتمالا اشتباه بود ولی چون اتوپلی خودش کامپایلر داره دیکامپایلر اتوپلی بی معنی یا اشتباه نیست، مستقیما هم کارکردش ربطی به لوا نداره.
طراحی کامپایلر یه اصولی داره، کسی که دکامپایلر طراحی می کنه هم اصول طراحی کامپایلر رو خوب می دونه و هم علم مهندسی معکوس رو بلد ئه. صد البته که در مورد ویندوز و api و فرمت فایل های اجرایی pe باید به قدر کافی اطلاعات داشته باشه. با مهندسی معکوس میشه از تبدیل نمونه کد به فایل اجرایی و تحلیل خروجی اش منطق کامپایلر رو فهمید، ولی خیلی زمانگیر ئه. به احتمال زیاد مستندات کامپایلرش رو هم به یه طریق دارند، از روی آزمون و خطا در آوردن OPCODE هر دستور خیلی وقت می گیره.

آها منظورتون اینه که بجای اینکه آرایه رو بصورت مستقیم از لوا بفرستم به سی شارپ ، بجاش آدرس اشاره گر اون آرایه رو از لوا بفرستم به سی شارپ و بعد با همین کلاس مارشال که گفتین ، اون اشاره گر رو (که Unmanaged بود) به آرایه ی Managed تبدیل کنم؟
اگه تعداد اعضای آرایه رو ندونم و هر بار که طرف فراخونی میکنه متفاوت باشه ، میشه بجای آرایه ی myPar که در بالا تعریف کردین ، از یه کلاس دینامیک مثل ArrayList و ... استفاده کنم تا راحت تر تعداد اعضاش رو متوجه شم؟

شما چه بخواهید و چه نخواهید اون اشاره گر رو به سی شارپ ارسال می کنید، لوا هر اصولی که داشته باشه نهایتا نمی تونه پارامتری بجز اشاره گر رو ارسال کرده باشه. اگه تعداد اعضاء رو ندونید باید به عنوان یک پارامتر مجزا تعداد اعضاء رو ارسال کنید. نمیشه از روی اشاره گر به تنهایی تعداد اعضاء رو تشخیص داد. بستگی به ساختار آرایه ها در لوا داره ولی بعید می دونم تعداد اعضاء در ابتدای آرایه ارسال شده باشه. ArrayList اینجا هیچ کمکی نمی تونه بکنه چون اولا با Marshal سازگاری نداره و اعضاء اش object ئه. ثانیا وقتی تعداد اعضاء رو ندونید هیچکدوم بدرد نمی خورند و اگر تعداد اعضاء رو بدونید آرایه به اندازه همون ArrayList کارایی داره. وقتی نمی دونید چند بایت داده باید از آدرس ptr بردارید دیگه آرایه با طول متغیر کاربردی نداره.
 
آخرین ویرایش:

جدیدترین ارسال ها

بالا