__Stdcall কি?


151

আমি উইন 32 প্রোগ্রামিং সম্পর্কে শিখছি, এবং WinMainপ্রোটোটাইপটি দেখে মনে হচ্ছে:

int WINAPI WinMain ( HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show )

এই WINAPIসনাক্তকারীটি কীসের জন্য ছিল এবং সে সম্পর্কে আমি বিভ্রান্ত হয়েছিলাম :

#define WINAPI      __stdcall

এটি কি করে? আমি রিটার্ন টাইপের পরে কিছু পেয়ে বিভ্রান্ত হয়ে পড়েছি। কিসের __stdcallজন্য? রিটার্ন টাইপ এবং ফাংশন নামের মধ্যে যখন কিছু থাকে তখন এর অর্থ কী?


2
@ অ্যান্ড্রুপ্রোক এই ক্ষেত্রে "ডামি" পরিবর্তনটি ঠিক ছিল, তবে সাধারণভাবে আপনি  ন্যূনতম (এবং প্রতি-উত্পাদনশীল - ক্ষেত্রে ক্ষেত্রে) ন্যূনতম 6 টি চরিত্রটি পেতে পারেন to
আদি ইনবার

উত্তর:


170

__stdcallফাংশনের জন্য ব্যবহৃত কলিং কনভেনশন। এটি সংকলককে সেই নিয়মগুলি বলে যা স্ট্যাক সেট আপ করার জন্য, তর্ক যুক্তিতে এবং রিটার্নের মান পাওয়ার জন্য প্রযোজ্য।

অন্যান্য কলিং নিয়মাবলী একটি নম্বর আছে, __cdecl, __thiscall, __fastcallএবং wonderfully নামে __declspec(naked)__stdcallউইন 32 সিস্টেম কলের জন্য আদর্শ কলিং কনভেনশন।

উইকিপিডিয়া বিবরণ আবরণ

এটি মূলত যখন আপনি আপনার কোডের বাইরে কোনও ফাংশন (যেমন একটি ওএস এপিআই) কল করছেন বা ওএস আপনাকে কল করছে (উইনমেইনের ক্ষেত্রে যেমনটি এখানে আসে) তখন এটি গুরুত্বপূর্ণ matters সংকলক যদি সঠিক কলিং কনভেনশন না জেনে থাকে তবে সম্ভবত খুব অদ্ভুত ক্রাশ হবে কারণ স্ট্যাকটি সঠিকভাবে পরিচালিত হবে না।


8
খুব starnge ক্র্যাশের উদাহরণের জন্য এই প্রশ্নের দেখুন stackoverflow.com/questions/696306/...
sharptooth

যদি আমি ভুল না হয়ে থাকি, তবে এই কলিং কনভেনশনগুলি নিয়ন্ত্রণ করে যে কীভাবে সংকলক সমাবেশ কোড তৈরি করে। অ্যাসেম্বলি কোডের সাথে হস্তক্ষেপ করার সময়, স্ট্যাকের সমস্যাগুলি রোধের জন্য কলিং কনভেনশনটি নোট করা উচিত তা সমালোচিত। এখানে কয়েকটি কনভেনশন ডকুমেন্ট করার জন্য একটি দুর্দান্ত টেবিল রয়েছে: এমএসডিএন.মাইক্রোসফট.ইন- ইউস
নিকোলাস মিলার

আমরা কি বলতে পারি যে এটি কিছু অবৈধ অপটিমাইজেশন অক্ষম করবে?
কেশারি

40

সি বা সি ++ নিজেই সেই শনাক্তকারীদের সংজ্ঞা দেয় না। এগুলি সংকলক এক্সটেনশন এবং নির্দিষ্ট কলিং কনভেনশনের পক্ষে দাঁড়ায়। এটি নির্ধারণ করে কোথায় আর্গুমেন্ট রাখা হবে, কোন ক্রমে, যেখানে ডাকা ফাংশনটি ফেরতের ঠিকানা খুঁজে পাবে এবং এই জাতীয় কিছু। উদাহরণস্বরূপ, __फाস্টকল মানে ফাংশনগুলির আর্গুমেন্টগুলি রেজিস্টারগুলিতে পাস করা হয়।

Wikipedia নিবন্ধটি সেখানে খুঁজে পাওয়া যায় নি বিভিন্ন কলিং নিয়মাবলী একটি ওভারভিউ প্রদান করে।


18

উত্তরগুলি এখনও পর্যন্ত বিশদগুলি কভার করেছে, তবে আপনি যদি সমাবেশে নেমে যেতে চান না, তবে আপনাকে কেবলমাত্র জানতে হবে যে কলার এবং কলি উভয়কে একই কলিং কনভেনশনটি ব্যবহার করা উচিত, অন্যথায় আপনি বাগ পাবেন যা খুঁজে পাওয়া শক্ত।


12

আমি একমত যে এখনও পর্যন্ত সমস্ত উত্তর সঠিক, তবে এখানে কারণ আছে। মাইক্রোসফ্ট এর সি এবং সি ++ সংকলক একটি অ্যাপ্লিকেশন এর সি এবং সি ++ ফাংশন মধ্যে ফাংশন কল গতি (উদ্দেশ্যে) গতি জন্য বিভিন্ন কলিং কনভেনশন প্রদান। প্রতিটি ক্ষেত্রে, আহ্বানকারী এবং কলি কোন কনলিং কনভেনশনটি ব্যবহার করবেন সে বিষয়ে অবশ্যই একমত হতে হবে। এখন, উইন্ডোজ নিজেই ফাংশন (এপিআই) সরবরাহ করে এবং সেগুলি ইতিমধ্যে সংকলিত হয়েছে, সুতরাং যখন আপনি তাদের কল করবেন তখন আপনাকে অবশ্যই সেগুলি মেনে চলতে হবে। উইন্ডোজ এপিআইগুলিতে যে কোনও কল এবং উইন্ডোজ এপিআইয়ের কলব্যাকগুলি অবশ্যই __stdcall কনভেনশনটি ব্যবহার করবেন।


3
এবং এটি _ স্ট্যান্ডার্ড_কলের সাথে বিভ্রান্ত হওয়া উচিত নয় যে এটি স্ট্যান্ডার্ড-সি! কেউ ভাবতে পারে যে এটি __stdcall এর মূল বিষয় হবে যদি কেউ আরও ভাল না জানে
জোহানেস স্কাউব - lit

3
একটি ছোট্ট নাইটপিক: কয়েকটি উইন্ডোজ এপিআই রয়েছে যা __stdcall এর পরিবর্তে __cdecl ব্যবহার করে - সাধারণত এমনগুলি যেগুলি ভেরিয়েবল সংখ্যার পরামিতি গ্রহণ করে, যেমন ডাব্লুস্প্রিন্টফ ()।
মাইকেল বারার

তুমি ঠিক বলছো. এটি সিআরটি ফাংশনের মতো দেখতে নাম দেওয়া হয়েছে তবে এটি একটি এপিআই। কোনও সুযোগে আপনি কীভাবে সি / এ থেকে পি / ইনভোকেট করবেন তা জানেন?
উইন্ডোজ প্রোগ্রামার

আমি এটি পরীক্ষা করে দেখিনি, তবে পিনভোক ডট নেট এই স্বাক্ষরটি দেয়: "স্ট্যাটিক এক্সটার্ন ইনট্রিএসপিএসফ ([আউট] স্ট্রিংবিল্ডার lpOut, স্ট্রিং lpFmt, ...);"
মাইকেল বারার

আমার অন্তর্নিহিততা বলছে যে সি # সংকলক সেইটিতে __cdecl কনভেনশনটি ব্যবহার করতে জানত না।
উইন্ডোজ প্রোগ্রামার


5

এটি কীভাবে ফাংশন বলা হয় তার সাথে এটি করা- মূলত যে জিনিসগুলিতে স্ট্যাক লাগানো হয় এবং পরিষ্কারের জন্য কে দায়ী।

এখানে ডকুমেন্টেশন রয়েছে তবে আপনি প্রথম অংশটি না বুঝলে এর অর্থ খুব বেশি নয়:
http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx


4

__stdcall স্ট্যাকের মধ্যে ফাংশন আর্গুমেন্ট রাখার জন্য ব্যবহৃত হয়। ফাংশনটি শেষ হওয়ার পরে এটি স্বয়ংক্রিয়ভাবে স্মৃতিটিকে ক্ষুণ্ন করে। এটি স্থির যুক্তিগুলির জন্য ব্যবহৃত হয়।

void __stdcall fnname ( int, int* )
{
    ...
}

int main()
{
    CreateThread ( NULL, 0, fnname, int, int*...... )
}

এখানে fnname টি args এটি সরাসরি স্ট্যাকের মধ্যে ধাক্কা।


1

আজ অবধি আমার আগে কখনও এটি ব্যবহার করতে হয়নি। এটি কারণ আমার কোডে আমি বহু-থ্রেডিং ব্যবহার করছি এবং মাল্টি-থ্রেডিং এপিআই যা আমি ব্যবহার করছি সেটি হ'ল উইন্ডোজ ওয়ান (_বিজেনথ্রেডেক্স)।

থ্রেড শুরু করতে:

_beginthreadex(NULL, 0, ExecuteCommand, currCommand, 0, 0);

এক্সিকিউটকম্যান্ড ফাংশনটি স্ট্রিমক্যাল কীওয়ার্ডটি পদ্ধতিতে স্বাক্ষরে ব্যবহার করতে হবে আরম্ভেরডেক্সকে কল করার জন্য:

unsigned int __stdcall Scene::ExecuteCommand(void* command)
{
    return system(static_cast<char*>(command));
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.