दिलचस्प पोस्ट
VBScript जैसे फ़ाइल सेसिफ्टऑब्जेक्ट के भीतर से नेटवर्क साझा करें एक्सेस-कंट्रोल-अनुमति-मूल सेट करने की सुरक्षा जोखिम क्या हैं? चेतावनी "PHP के लिए नेटबीन्स 7.4 पर" सुपर ग्लोबल $ _POST सरणी पर सीधे प्रवेश न करें " क्लोज़र में जावा चर लंबाई तर्क को कैसे नियंत्रित करें? क्या मैं जावा स्रोत फाइलों में मैक्रोज़ कर सकता हूं? ईएफ संहिता में सबसे पहले मैं अपने तालिकाओं को कैसे अलग करता हूं? यह प्रतीक जावास्क्रिप्ट में क्या मतलब है? मैं जावा 8 स्ट्रीमों के साथ कार्टेशियन उत्पाद कैसे बना सकता हूं? ब्राउज़र में वीएमएल या एसवीजी के लिए समर्थन का पता कैसे लगाया जाता है Highcharts के साथ JSON के माध्यम से चार्ट डेटा को पुनः लोड करें कुशलता से एक पाठ फ़ाइल की लाइनों की संख्या की गिनती। (200MB +) केंद्र में "x" के साथ लापता टाइल के साथ नक्शादृश्य प्रस्तुत करना पैटर्न का उपयोग क्या है। प्रश्न विधि? मापा संकेत का पीक पहचान कैसे Xcode में आईओएस क्षुधा को iPhone 5 बड़े स्क्रीन समर्थन जोड़ने के लिए?

64 बिट डेल्फी में नेस्टेड स्थानीय फ़ंक्शन को क्यों नहीं ले जा सकता?

जैसा। संबंधित प्रश्नों को बंद करने के बाद – नीचे और उदाहरण जोड़ा गया।

नीचे सरल कोड (जो एक शीर्ष-स्तरीय आईई खिड़की पाता है और अपने बच्चों को एन्यूमरेट करता है) ठीक एक '32-बिट विंडोज' लक्ष्य प्लेटफॉर्म के साथ काम करता है। डेल्फी के पूर्व संस्करणों में भी कोई समस्या नहीं है:

procedure TForm1.Button1Click(Sender: TObject); function EnumChildren(hwnd: HWND; lParam: LPARAM): BOOL; stdcall; const Server = 'Internet Explorer_Server'; var ClassName: array[0..24] of Char; begin Assert(IsWindow(hwnd)); // <- Assertion fails with 64-bit GetClassName(hwnd, ClassName, Length(ClassName)); Result := ClassName <> Server; if not Result then PUINT_PTR(lParam)^ := hwnd; end; var Wnd, WndChild: HWND; begin Wnd := FindWindow('IEFrame', nil); // top level IE if Wnd <> 0 then begin WndChild := 0; EnumChildWindows(Wnd, @EnumChildren, UINT_PTR(@WndChild)); if WndChild <> 0 then .. end; 

मैंने यह इंगित करने के लिए एक Assert डाली है कि यह एक '64-बिट Windows 'लक्ष्य प्लेटफ़ॉर्म के साथ विफल रहता है। कोड के साथ कोई समस्या नहीं है, अगर मैं कॉलबैक को बंद कर देता हूं।

मुझे यकीन नहीं है कि मानदंडों के साथ गलत मूल्यों को पारित किया गया है, केवल कूड़ेदान हैं या कुछ गलत तरीके से रखे स्मृति पते (सम्मेलन को बुला रहे हैं?) के कारण हैं। घोंसले के शिकार कॉलबैक वास्तव में कुछ है जो मुझे पहले स्थान पर कभी नहीं करना चाहिए? या यह सिर्फ एक दोष है जिसके साथ मैं रहना है?

संपादित करें:
दाऊद के उत्तर के जवाब में, एक ही कोड को EnumChildWindows एक टाइप कॉलबैक के साथ घोषित किया गया। 32-बिट के साथ ठीक काम करता है:

(संपादित करें: नीचे वास्तव में यह परीक्षण नहीं है कि डेविड क्या कहता है क्योंकि मैं अब भी '@' ऑपरेटर का उपयोग करता हूं। यह ऑपरेटर के साथ ठीक काम करता है, लेकिन अगर मैं इसे हटा देता हूं, तो यह वास्तव में संकलन नहीं करता है जब तक कि मैं बिना कॉलबैक को बंद कर देता हूं)

 type TFNEnumChild = function(hwnd: HWND; lParam: LPARAM): Bool; stdcall; function TypedEnumChildWindows(hWndParent: HWND; lpEnumFunc: TFNEnumChild; lParam: LPARAM): BOOL; stdcall; external user32 name 'EnumChildWindows'; procedure TForm1.Button1Click(Sender: TObject); function EnumChildren(hwnd: HWND; lParam: LPARAM): BOOL; stdcall; const Server = 'Internet Explorer_Server'; var ClassName: array[0..24] of Char; begin Assert(IsWindow(hwnd)); // <- Assertion fails with 64-bit GetClassName(hwnd, ClassName, Length(ClassName)); Result := ClassName <> Server; if not Result then PUINT_PTR(lParam)^ := hwnd; end; var Wnd, WndChild: HWND; begin Wnd := FindWindow('IEFrame', nil); // top level IE if Wnd <> 0 then begin WndChild := 0; TypedEnumChildWindows(Wnd, @EnumChildren, UINT_PTR(@WndChild)); if WndChild <> 0 then .. end; 

असल में यह सीमा एक Windows एपीआई कॉलबैक के लिए विशिष्ट नहीं है, लेकिन वही समस्या तब होती है जब उस फ़ंक्शन को procedural type एक चर में लेते हैं और इसे पारित करते हैं, उदाहरण के लिए, TList.Sort लिए कस्टम तुलनित्र के TList.Sort

http://docwiki.embarcadero.com/RADStudio/XE4/en/Procedural_Types

 procedure TForm2.btn1Click(Sender: TObject); var s : TStringList; function compare(s : TStringList; i1, i2 : integer) : integer; begin result := CompareText(s[i1], s[i2]); end; begin s := TStringList.Create; try s.add('s1'); s.add('s2'); s.add('s3'); s.CustomSort(@compare); finally s.free; end; end; 

यह 32-बिट के रूप में संकलित होने पर अपेक्षित काम करता है, लेकिन Win64 के लिए संकलित होने पर Access Violation साथ विफल रहता है। समारोह में 64-बिट संस्करण की compare , s = nil और i2 = कुछ यादृच्छिक मूल्य;

यह Win64 के लक्ष्य के लिए भी अपेक्षित काम करता है, अगर कोई btn1Click फ़ंक्शन के बाहर फ़ंक्शन को btn1Click है।

Solutions Collecting From Web of "64 बिट डेल्फी में नेस्टेड स्थानीय फ़ंक्शन को क्यों नहीं ले जा सकता?"

इस चाल को कभी भी आधिकारिक रूप से भाषा द्वारा समर्थित नहीं किया गया था और आप 32 बिट संकलक के क्रियान्वयन के विशेष कारणों से अब तक इसे दूर कर रहे हैं। प्रलेखन स्पष्ट है:

नेस्टेड प्रक्रियाएं और कार्य (अन्य दिनचर्याओं में घोषित दिनचर्या) प्रक्रियात्मक मूल्यों के रूप में उपयोग नहीं किए जा सकते।

यदि मुझे सही ढंग से याद आती है, तो एक अतिरिक्त, छिपे हुए पैरामीटर को नेस्टेड फ़ंक्शंस के साथ समेटे जाने वाले स्टैक फ्रेम में पॉइंटर के पास दिया जाता है। इसे 32 बिट कोड में छोड़ा गया है यदि कोई परिवेशी वातावरण में कोई संदर्भ नहीं बनाया गया है। 64 बिट कोड में अतिरिक्त पैरामीटर हमेशा पारित किया जाता है

बेशक समस्या का एक बड़ा हिस्सा यह है कि विंडोज़ यूनिट अपने कॉलबैक मापदंडों के लिए अप्रयुक्त प्रक्रिया प्रकार का उपयोग करता है। यदि टाइप की गई प्रक्रियाओं का उपयोग किया गया था तो कंपाइलर आपके कोड को अस्वीकार कर सकता है। वास्तव में मैं इसे विश्वास के लिए औचित्य के रूप में मानता हूं कि आपके द्वारा उपयोग की जाने वाली चालन कभी कानूनी नहीं थी। टाइप किए गए कॉलबैक के साथ नेस्टेड प्रक्रिया का उपयोग कभी नहीं किया जा सकता, यहां तक ​​कि 32 बिट कंपाइलर में भी।

वैसे भी, निचला रेखा यह है कि आप नेस्टेड फ़ंक्शन पैरामीटर के रूप में 64 बिट कंपाइलर में किसी अन्य फ़ंक्शन के पास नहीं कर सकते।