استفاده از کد سی در دلفی
انواع فراخوانی توابع
توابع در یک زبان برنامه نویسی بسته به روش فرستادن آرگومانها به تابع، جهت قرار گرفتن آرگومانها در پشته و یا رجیسترها و نوع پاکسازی پشته بعد از پایان تابع، به چند دسته تقسیم میشوند.:
1. register
در این نوع برای فرستادن آرگومانها به تابع از ثباتهای حافظه (رجیسترها) استفاده میشود. در این حالت آرگومانها از چپ به راست در رجیسترها قرار گرفته و به تابع پاس داده میشوند. این نوع توابع خودشان بعد از پایان کار فضا و پشته را خالی میکنند. نوع فراخوانی پیشفرض برای دلفی حالت register است.
2. pascal (__pascal در C)
در این نوع، آرگومانها از طریق پشته (Stack ) به تابع فرستاده میشوند، آرگومانها از چپ به راست در پشته قرار میگیرند و تابع بعد از پایان کار و پیش از بازگشت پشته را خالی میکند. این حالت صرفا برای پشتیبانی از کدهای قدیمی هنوز پشتیبانی میشود.
3. cdecl ( __cdecl در C )
آرگومانهای این نوع، از طریق پشته به تابع فرستاده میشوند و از راست به چپ در پشته قرار میگیرند. تابع بعد از پایان کار پشته را خالی نمیکند و صدازننده تابع بایست این کار را انجام دهد. حالت پیشفرض در C و برای توابع سیستمی برای سیستم عامل های غیر ویندوز همین نوع است.
4. stdcall (__stdcall در C )
آرگومانها از طریق پشته و از راست به چپ به تابع فرستاده میشوند. تابع بعد از پایان کار پشته را خالی میکند. کلیه API های سیستم عامل ویندوز از این نوع هستند.
5. safecall (__safecall در C )
این نوع فراخوانی دقیقا شبیه حالت stdcall است با این تفاوت که در برابر خطاهای اتفاق افتاده در تابع مثل یک دیوار عمل میکند و خطا را (در صورتی که در تابع تله گذاری نشده باشد ) به صدا زننده تابع برنمیگرداند و معمولا برای پیاده سازی تکنولژی COM از آن استفاده میشود. در این نوع تابع، بازگشتی به صورت آرگومان آخر فرستاده میشود (به عبارتی یک آرگومان به تابع اضافه میشود ) و بازگشتی اصلی به صورت HRESULT میشود که در صورت موفقیت کد S_OK و در غیر اینصورت خطای اتفاق افتاده را باز میگرداند.
فراخوانی تابعی از یک نوع به نوع دیگر باعث خطاهایی خواهد شد که تشخیص آن هنگام برنامه نویسی نسبتا مشکل است.
البته منظور از طریقه پاکسازی پشته یا طریقه فرستادن آرگومانها این نیست که برنامه نویس بایستی خودش این کار را انجام دهد، کامپایلر هنگام کامپایل عملیات لازم مربوط به این مراحل را به کد اضافه میکند.
حالتهای توصیه شده برای توابع در ویندوز stdcall و safecall هستند. برای مشخص کردن نوع تابع در دلفی کافی است یک از کلیدواژه های معرفی شده را در پایان معرفی تابع قرار دهیم :
کد:
function MyFunc(Arg1 : Integer ; Arg2 : Integer):Integer;stdcall;
در C بایستی نوع تابع را قبل از نام تابع و بعد از نوع بازگشتی مشخص کنیم :
کد:
int __stdcall myfunc (int arg1, int arg2 );
همانطور که گفته شد دلفی توابع بدون مشخصه را register و C آنها را cdecl در نظر میگیرد.
کامپایلر های C معمولا هنگام کامپایل یک علامت زیرخط (_) به آغاز نام توابع cdecl اضافه میکنند و نام توابع نوع pascal تماما به حروف بزرگ تبدیل میشود.
کامپایل فایلهای C توسط Borland C++ Builder به فایلهای Obj
طریقه کامپایل فایل های c و تبدیل آنها به فایلهای obj بدون ایجاد فایل نهایی بسیار ساده است. دستوری شبیه زیر را از طریق خط فرمان یا یک Batch فایل اجرا کنید
BCC32.EXE options] file1.c file2.c …
به جای BCC32.EXE آدرس کامل این فایل (که در پوشه bin در مکان نصب C++ Builder قرار دارد) را بنویسید و به جای options انتخابهایی را که چندتایی از آنها در ادامه معرفی میشوند و بالاخره در انتها لیست فایلهایی که میخواهید کامپایل کنید را بنویسید. مثلا :
کد:
C:\Borland\BCC55\Bin\BCC32.EXE -c -X -v -u- test1.c test2.c
حروف کوچک و بزرگ در مورد انتخابها (options ) مهم هستند اما در مورد نام فایلها نه. هر انتخاب با یک علامت منفی (-) در سمت چپ مشخص میشود و گذاشتن یک منفی در سمت راست به معنی حذف این انتخاب از لیست انتخابهاست.بعضی option ها که مورد نیاز هستند را در اینجا توضیخ میدهیم. باقی این موارد را میتوانید در راهنمایC++ Builder ببینید.
-c : این انتخاب به کامپایلر اعلام میکند که بعد از پایان کامپایل Linker را فراخوانی نکند و به جای ساختن فایل نهایی (فایل exe یا dll و یا... ) فقط فایلهای Obj را بسازد.
-X : این انتخاب باعث میشود که کامپایلر طلاعات مربوط به فایلهای سرآمد (Header فایلهای C ) را به فایل Obj اضافه نکند. در حالت عادی کامپایلر این کار را میکند. دلفی نیازی به این اطلاعات ندارد و ان انتخاب حجم فایلهای Obj را کم میکند.
-v :این انتخاب اطلاعات مربوط به Debug را نیز به Obj فایل اضافه میکند. این به شما اجازه میدهد هنگام تست برنامه در دلفی و Trace آن از طریق کلید F7 کد C را هم در محیط دلفی دنبال کنید. (البته در صورتی که اصل فایلها به زبان C موجود باشد و شما تنها Obj فایلها را نداشته باشید.) این انتخاب اندازه فایلهای Obj را تا خد زیادی افزایش میدهد و تنها برای زمانی مناسب است که برنامه در مرحله تست و خطایابی است. در هنگام انتشار بهتر است این انتخاب هنگام کامپایل برداشته شود.
-u- : هنگام کامپایل، کامپایلر C++ Builder یک علامت زیرخط (_) به توابع با نوع فراخوانی cdecl اضافه میکند (حالت پیشفرض -u است) شما با گذاشتن یک منفی در سمت راست میتوانید این گزینه را غیر فعال کنید. در این صورت کلیه توابع cdecl با نام خودشان در فایل Obj قرار میگیرند.
-pr : نوع فراخوانی پیشفرض توابع را از cdecl به register تبدیل میکند. در این حالت تمام توابعی که نوع فراخوانی آنها مشخص نیست به نوع register تبدیل میشوند.
افرودن فایلهای Obj به کد دلفی
به دلیل شباهت لینکرهای C++ Builder و Delphi برای افزودن یک فایل Obj کامپایل شده توسط C++ Builder - و البته خود دلفی - به دلفی میتوانید از دستور پیش پردازنده $L استفاده کنید. مثلا {$L fileName.obj} و سپس کافی است کلیه توابعی که در فایل Obj هستند و نیازمند استفاده از آنها در C هستید را با یک اعلان پیشرو و به صورت external تعریف کنید. در این حالت توابع مورد استفاده که با کامپایلر C++ Builder کامپایل شده اند با لینکر دلفی به برنامه لینک میشوند.