PDA

View Full Version : سوال درباره تعریف procedure یا function



RCE Master
شنبه 20 بهمن 1386, 17:57 عصر
آیا امکان تعریف تابع یا procedure با تعداد پارامتر متغییر وجود دارد؟ overload مشکل منو حل نمیکنه می خوام یک بار کد بنویسم. مثلا:
int FnKernelSet(HCORE hKernel, DWORD dwOptionId, ...);
اگر امکانش هست لطفا توضیح بدید.

vcldeveloper
یک شنبه 21 بهمن 1386, 02:30 صبح
بصورت عادی نه. ولی می تونید یک پارامتر از نوع Variant تعریف کنید و با آن بصورت array of Variant کار کنید. نتیجه اش میشه آرایه ایی با طول مشخص که عناصر آن type های مختلفی دارند. برای تولید همچین آرایه ایی باید از VarArrayCreate یا VarArrayOf استفاده کنید. در Help دلفی برای این توابع مثال زذه شده. یک نمونه اش هم متد Locate از TDataSet هست که مقادیر فیلدهایی که باید جستجو بشند را بدون آنکه از قبل تعداد فیلدها و نوع داده هر فیلد مشخص باشه، دریافت میکنه. این متد هم در Help دلفی با مثال توضیح داده شده.

RCE Master
یک شنبه 21 بهمن 1386, 11:03 صبح
اونوقت calling conversion و نحوه پاس دادن پارامترها چی میشه؟ من می خوام از یه همچین تابعی که تو ی DLL و با زبان ++C نوشته شده استفاده کنم یعنی import کنم. از کجا میفهمه چند تا پارامتر تو stack داریم که بعدش هم بتونه درست از تابع خارج بشه.

vcldeveloper
یک شنبه 21 بهمن 1386, 23:28 عصر
اونوقت calling conversion و نحوه پاس دادن پارامترها چی میشه؟ من می خوام از یه همچین تابعی که تو ی DLL و با زبان ++C نوشته شده استفاده کنم یعنی import کنم.
نه اینو توی پست اول نگفته بودی. اونی که گفتم فقط برای دلفی هست. اون در واقع یک Dynamic Array هست که هر یک از المان هاش بصورت variant تعریف شده باشند. حتی اگر فرض بگیریم Variant به همون شکلی در دلفی هست، در ++C هم وجود داشته باشه، Dynamic Array از Type های خاص دلفی هست که در ++C وجود نداره، یا به این شکل تعریف نشده.

Inprise
دوشنبه 22 بهمن 1386, 07:50 صبح
اونوقت calling conversion و نحوه پاس دادن پارامترها چی میشه؟ من می خوام از یه همچین تابعی که تو ی DLL و با زبان ++C نوشته شده استفاده کنم یعنی import کنم. از کجا میفهمه چند تا پارامتر تو stack داریم که بعدش هم بتونه درست از تابع خارج بشه.

Calling Convention دراین موارد همیشه stdcall هست . ولی مسئله ای که مشکل ایجاد میکنه این نیست . علی کشاورز توضیح داد . ولی چرا overload مشکلت رو حل نمیکنه ؟ یعنی چه مشکلی هست اساسا ؟

RCE Master
یک شنبه 28 بهمن 1386, 13:58 عصر
stdcall نیست مثل اینکه چوبراشون مهم نبوده غیر C تو زبانهای دیگه هم بشه Import کرد. توی C که خودشون با همون تعریف بدون stdcall تعریف کرده بودن. من این function رو trace کردم این تابع کاری نداره به جای اون ... (پارامتری که 3 تا نقطه تعریف شده) چند تا پارامتر پاس می کنی یا اصلا پاس نمیکنی کارشو انجام میده میاد بیرون به stack هم دست نمیزنه. اصلا انگار نمیتونه هم stdcall باشه چون تعداد پارامتر هاش مشخص نیست که بتونه اونا رو از stack بندازه بیرون چون تو stdcall بعد خروج دیگه ÷ارامتر ها از stack برداشته شده. نمی دونم تو دلفی همچین چیزی داریم یا نه ولی به هر حال خود این function رو اینجوری میشه فراخوانی کرد.
push param1
push param2
push ...
push param(n)
call fn

بعد به تعداد پارامتر هایی که تو stack میذاریم دیگه بعد خروج خودمون باید stack رو درست کنیم. خوب حالا یه تابعی که باید اینو پوشش بده چه جوری باید نوشته بشه اگه arrayof variant بذاریم....؟؟؟
توی C میاد رشته Push میکنه آدرس رشته PChar میره Int رو push میکنه خود عدد میره ولی تو ِDelphi من نمی تونم این کار رو بکنم.

Inprise
یک شنبه 28 بهمن 1386, 16:08 عصر
واقعیتش رو بخواهی من خیلی تلاش کردم و متاسفانه یک کلمه از مطلبی که نوشتی رو متوجه نشدم . نه تنها این مطلب ، که اصلا در کل نفهمیدم که مسئله ات چیه . جوابت رو در مورد Convention و تعدد پارامتر گرفتی فکر میکنم . مسئله ای که حل نشده ، یا مشکلی که داری رو بدون اینکه تحلیلش کنی بگو .

RCE Master
دوشنبه 29 بهمن 1386, 15:18 عصر
کل قضیه رو این جوری میشه توضیح داد:
یه DLL داریم که یه سری function رو Export کرده و یه سورس کد به زبان ++C که از اون DLL استفاده میکنه. حالا من میخوام این DLL رو توی دلفی ازش استفاده کنم. مشکل این هست که می خوام این تابع رو استفاده کنم ازش.همه چی رو به راه هست فقط این یکی Export که تو DLL هست یه کم عجیب غریب به نظرم میاد.
int FnKernelSet(HCORE hKernel, DWORD dwOptionId, ...);
توی سورس ++C که از DLL استفاده شده یه Pointer از جنس این تابع تعریف شده و با GetProcAddress بهش مقدار داده شده.
اگه بشه تو دلفی یه type از نوع function تعریف کرد که معادل این تعریف توی زبان ++C باشه که خیلی عالیه. ولی من فرض رو به این گذاشتم که نمیشه و شروع کردم یه راه دیگه براش پیدا کنم.

حالا کارهایی که خودم کردم هم یه توضیحی میدم احتمالا برای حل مشکل مفید باشه.
همونطور که میبینید اینجا به جای پارامتر سوم ... گذاشته من حقیقتش تا حالا همچین چیزی ندیده بودم ولی به این معنی هست که تابع رو حداقل با 2 تا پامتر مشخص باید فراخوانی کرد بیشتر هم میشه و type هاشون هم برای کمپایلر اصلا فرقی نداره چی باشه. به هر حال تو Visual Studio من DisAssembly برنامه رو نگاه کردم:
جایی که با 2 تا پارامتر تابع رو فراخونی کرده اول پارامتر دوم push میشه بعد پارامتر اول بعد تابع call میشه حالا وقتی روی call کلید F10 رو میزنی بدون اینکه ESP تغییری بکنه از تابع اومده بیرون (ولی میدونید که تو stdcall برای 2 تا پارامتر 8 تا به ESP اضافه میشه یعنی stdcall مثل API های ویندوز پارامتر ها رو برمیداره از stack)
وقتی تو C همین تابع رو با پارامترهای بیشتری call میکنه همونا رو هر چی که هست همینجوری push میکنه و تابع رو call میکنه. حالا تو Delphi مثلا بخوایم با n تا پارامتر این تابع رو صدا بزنیم میشه اینجوری:
asm
push param n push param(n-1)
.
.
.
push param1
call func
mov edx,n
shl edx,2
add esp,edx
end;
خوب پس تا الان میدونیم که چه جوری میشه اینو call کرد ولی type ها و تعداد پارامترها باهم فرق داره و Variant هم که push میکنی یه عدد push میکنه که اصلا معلوم نیست چی هست. نمیدونم دیگه بقیه کار رو چه جوری میشه تکمیلش کرد.
امیدوارم تونسته باشم مشکل رو درست مطرح کنم.

B-Vedadian
دوشنبه 19 فروردین 1387, 10:51 صبح
وقتی در Visual C++ برنامه می نویسید، روش پیشفرض همانطور که آقای اینپرایز گفت، stdcall هستش. تابعی که شما می خوای باهاش کار کنی، توی دلفی معادن نداره.

در ضمن اینجور توابع بدون توجه به نوع داده ورودی کار نمی کنند، یه جایی براش معین می کنی که چه جور پارامترهایی داری براش میفرستی. برای مثال به تابع printf و مشابهاش مراجعه کن.

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