यह बिल्कुल एक सीधा सवाल नहीं है क्योंकि मैंने इसे हल किया है, लेकिन जैसे "मैं इसे सही कर रहा हूं" प्रश्न और प्रश्नों के लिए एक अनुस्मारक जो अटक सकता है उस में।डेल्फी स्टैक misalignment + com marshalling = गलत marshalling
बाहर निकलता है, डेल्फी स्टैक पर चर संरेखित नहीं करता है और इस व्यवहार को नियंत्रित करने के लिए कोई निर्देश/विकल्प नहीं हैं। मेरे एक्सपी एसपी 3 पर डिफॉल्ट COM मार्शलर को रिकॉर्ड करते समय 4-बाइट संरेखण की आवश्यकता होती है। इससे भी बदतर, जब यह असाइन किए गए पॉइंटर से मुकाबला करता है, तो यह कोई त्रुटि नहीं देता है, ओह नहीं: यह पॉइंटर को निकटतम 4-बाइट सीमा तक ले जाता है और इस तरह जारी रहता है।
इसलिए, यदि आप एक रिकॉर्ड पास करते हैं तो आपने संदर्भ द्वारा COM-marshaled फ़ंक्शन में स्टैक पर आवंटित किया है, तो आप खराब हो गए हैं और आपको यह भी पता नहीं चलेगा।
समस्या को आवंटित करने के लिए नई/निपटान का उपयोग करके हल किया जा सकता है, क्योंकि स्मृति प्रबंधक 8 बाइट्स या बेहतर पर सबकुछ संरेखित करते हैं, लेकिन भगवान, यह कष्टप्रद भाग और "ट्रिम-डाउन पॉइंटर्स" " अंश।
क्या यह वास्तव में कारण है, या क्या मैं कहीं गलत हूं?
अद्यतन: पुन: पेश करने के लिए (Win32 के लिए डेल्फी 2007)।
uses SysUtils;
type
TRec = packed record
a, b, c, d, e: int64;
end;
TDummy = class
protected
procedure Proc(param1: integer);
end;
procedure TDummy.Proc(param1: integer);
var a, b, c: byte;
rec: TRec;
begin
a := 5;
b := 9;
c := 100;
rec.a := param1;
rec.b := a;
rec.c := b;
rec.d := c;
writeln(IntToHex(integer(@rec), 8));
readln;
end;
var Obj: TDummy;
begin
obj := TDummy.Create;
try
obj.Proc(0);
finally
FreeAndNil(obj);
end;
end.
यह अजीब परिणाम पता देता है, स्पष्ट रूप से कुछ भी गठबंधन नहीं करता है। यदि ऐसा नहीं होता है, तो "ए, बी, सी: बाइट" में अधिक बाइट वेरिएबल्स जोड़ने का प्रयास करें (और फ़ंक्शन के अंत में उनके साथ कुछ काम अनुकरण करना न भूलें)।
COM के साथ भाग पुन: पेश करना आसान है लेकिन व्याख्या करने में लंबा है। नमूना सर्वर नामक एक नया वीसीएल ऐप बनाएं, एक COM ऑब्जेक्ट नमूना ऑब्जेक्ट लागू करें ISampleObject, टाइप लाइब्रेरी, फ्री-थ्रेडेड, सिंगल इंस्टेंस के साथ (सुनिश्चित करें कि ISampleObject को टाइप लाइब्रेरी में ओले ऑटोमेशन के रूप में चिह्नित किया गया है)। टाइप लाइब्रेरी खोलें, पांच __int64 फ़ील्ड के साथ एक नया नमूना रिकॉर्ड घोषित करें। ISampleObject के लिए एक नमूना रिकॉर्ड * आउट पैरामीटर के साथ एक नमूना समारोह जोड़ें। TSampleObject में SampleFunction लागू लौटने तय मूल्यों से:
function TSampleObject.SampleFunction(out rec: SampleRecord): HResult;
begin
rec.a := 1291;
rec.b := 742310;
//...
Result := S_OK;
end;
नोट कैसे डेल्फी "पैक रिकॉर्ड" स्वचालित रूप से उत्पन्न प्रकार लायब्रेरी हैडर कोड में के रूप में वाणी SampleRecord:
SampleRecord = packed record
a: Int64;
b: Int64;
//...
end;
मैं जाँच की है, और यह कम से कम , डेल्फी 2010 में तय किया गया था। स्वचालित रूप से जेनरेट किए गए रिकॉर्ड वहां पैक नहीं होते हैं।
COM सर्वर पंजीकृत करें। चलाओ।
अब (नमूना 1) ऊपर स्रोत को संशोधित बस कर writeln के बजाय इस सर्वर कॉल करने के लिए:
uses SysUtils, Windows, ActiveX, SampleServer_TLB;
procedure TDummy.Proc(param1: integer);
var a, b, c: byte;
rec: SampleRecord;
Server: ISampleObject;
begin
a := 5;
b := 9;
c := 100;
rec.a := param1;
rec.b := a;
rec.c := b;
rec.d := c;
Server := CoSampleObject.Create;
hr := Server.SampleFunction(rec);
writeln('@: 'IntToHex(integer(@rec), 8)+', rec.a='+IntToStr(rec.a));
readln;
end;
var Obj: TDummy;
begin
CoInitializeEx(nil, COINIT_MULTITHREADED);
obj := TDummy.Create;
try
obj.Proc(0);
finally
FreeAndNil(obj);
CoUninitialize();
end;
end.
गौर करें कि जब आरईसी का पता मेल नहीं किया गया, आरईसी फ़ील्ड के मानों का गलत हैं (विशेष रूप से, 8, 16 या 24 बिट्स तक बिट्सफ़िफ्ट किया गया, कभी-कभी अगले मान पर लपेटा जाता है)।
डेल्फी का कौन सा संस्करण, मेमोरी मैनेजर क्या है? क्या आप एक उदाहरण प्रदान कर सकते हैं जिसे हम आजमा सकते हैं? –
डेल्फी 2007, फास्टएमएम 4 के बाहर बॉक्स। उदाहरण जोड़े गए। – himself
कृपया इस परीक्षण मामले के साथ गुणवत्ता केंद्र में एक रिपोर्ट दर्ज करें; http://qc.embarcadero.com –