2013-04-20 5 views
7

से फ़ंक्शन परिणाम के रूप में रिकॉर्ड पास करना मुझे अभी कुछ अजीब चीज़ों का सामना करना पड़ रहा है। जब मैं पैरामीटर के रूप में C++ से डेल्फी डीएलएल में एक स्ट्रक्चर पास कर रहा हूं, सबकुछ ठीक काम करता है। हालांकि, जैसे ही मैं परिणाम के रूप में एक रिकॉर्ड प्राप्त करना चाहता हूं, मुझे या तो गलत मान या अपवाद मिलते हैं। मैंने रिकॉर्ड के संरेखण को निष्क्रिय कर दिया ताकि उन्हें गुजरना चाहिए! कोड है!डेल्फी डीएलएल से सी ++

डेल्फी DLL:

TSimpleRecord = packed record 
    Nr1 : Integer; 
    Nr2 : Integer; 
end; 

//... 

function TTest() : TSimpleRecord; cdecl; 
begin 
    Result.Nr1 := 1; 
    Result.Nr2 := 201; 
    ShowMessage(IntToStr(SizeOf(Result))); 
end; 

सी ++ कॉल:

#pragma pack(1) 
struct TSimpleRecord 
{ 
    int Nr1; 
    int Nr2; 
}; 

//... 

    typedef TSimpleRecord (__cdecl TestFunc)(void); 
    TestFunc* Function; 
    HINSTANCE hInstLibrary = LoadLibrary("Reactions.dll"); 
    if (hInstLibrary) 
    { 
     Function = (TestFunc*)GetProcAddress(hInstLibrary, "TTest"); 
     if (Function) 
     { 
      TSimpleRecord Result = {0}; 
      Result = Function(); 
      printf("%d - %d - %d", sizeof(Result), Result.Nr1, Result.Nr2); 
      cin.get(); 
     } 
    } 

मैं पता नहीं क्यों एक पैरामीटर के रूप में काम करता है इस रिकॉर्ड गुजर मिल गया है लेकिन एक समारोह का एक परिणाम के रूप में नहीं !?

किसी को भी मेरी मदद कर सकते `

धन्यवाद

पुनश्च:? जैसा कि मैंने कहा, दोनों सी ++ और डेल्फी बताते हैं कि रिकॉर्ड 8 बाइट्स बड़ी है।

+0

क्या आप वास्तव में डेल्फी फ़ंक्शन में वापसी मान सेट कर रहे हैं? – Angew

+0

परिणाम एनआर 1: = 1; परिणाम। एनआर 2: = 201; उस काम को – Henry

+0

करना चाहिए क्षमा करें, आखिरकार जब मैंने डेल्फी के साथ बातचीत की, तो 'परिणाम' अभी भी फ़ंक्शन पहचानकर्ता, आईआईआरआर का उपयोग करता था। – Angew

उत्तर

5

कुछ कंपाइलर struct प्रकार (संभावित रूप से आकार के आधार पर) रजिस्टरों में वापस आ जाएंगे, अन्य एक छुपा अतिरिक्त पैरामीटर जोड़ देंगे जहां परिणाम संग्रहीत किया जाना चाहिए। दुर्भाग्यवश, ऐसा लगता है कि आप दो कंपाइलर्स से निपट रहे हैं जो इन्हें वापस करने के तरीके से सहमत नहीं हैं।

आप इसके बजाय out पैरामीटर का स्पष्ट रूप से उपयोग करके समस्या से बचने में सक्षम होना चाहिए।

procedure TTest(out Result: TSimpleRecord); cdecl; 
begin 
    Result.Nr1 := 1; 
    Result.Nr2 := 201; 
end; 

तदनुसार C++ कोड को अपडेट करना न भूलें।

Rudy Velthuis has written about this:

यह मैं पता चला है कि ABCVar struct रजिस्टरों EDX में वापस आ गया था: EAX (शीर्ष 32 बिट के साथ EDX, और कम लोगों के साथ EAX)। डेल्फी रिकॉर्ड के साथ ऐसा नहीं करता है, न कि इस आकार के रिकॉर्ड के साथ भी। डेल्फी अतिरिक्त रिटर्न पैरामीटर के रूप में ऐसे रिटर्न प्रकारों का इलाज करता है, और कुछ भी वापस नहीं करता है (इसलिए फ़ंक्शन वास्तव में एक प्रक्रिया है)।

[...]

केवल प्रकार है जो डेल्फी EDX के रूप में प्रस्तुत करती है: EAX संयोजन Int64 है।

जो पता चलता है कि एक वैकल्पिक तरीका समस्या से बचने के है

function TTest() : Int64; cdecl; 
begin 
    TSimpleRecord(Result).Nr1 := 1; 
    TSimpleRecord(Result).Nr2 := 201; 
end; 

ध्यान दें कि डेल्फी भी स्थितियों में, जहां व्यवहार सी में अपरिभाषित किया जाएगा में इस प्रकार punning की अनुमति देता है ++।

+0

धन्यवाद, बिल्कुल वही जो मैं खोज रहा था! भले ही Int64 का उपयोग करने वाला उदाहरण मेरे लिए काम नहीं करता – Henry

+0

@ हेनरी यह किस तरह से काम नहीं करता है? क्या यह आपको एक त्रुटि संदेश देता है, या फिर भी आपको गलत व्यवहार मिलता है? मैं पूछता हूं क्योंकि मैंने सत्यापित किया है कि एक स्टैंडअलोन एप्लिकेशन में परिणाम रजिस्टरों (इच्छित के रूप में) में वापस आ गया है। खुशी है कि समस्या से बचने का दूसरा तरीका काम कर रहा है, वैसे भी :) – hvd

+0

हालांकि मैं मानता हूं कि Int64 चाल काम करना चाहिए। इस तरह मैंने सभी दस्तावेज़ों को पढ़ा। –

1

डेल्फी रिटर्न मूल्यों के लिए प्लेटफॉर्म मानक एबीआई का पालन नहीं करता है। मानक एबीआई मूल्य के आधार पर कॉलर को रिटर्न वैल्यू पास करता है। डेल्फी रिटर्न वैल्यू को एक अन्य अतिरिक्त पैरामीटर के रूप में पारित एक अंतर्निहित अतिरिक्त var पैरामीटर के रूप में मानता है। documentation नियमों का वर्णन करता है।

आप मिलान करने के लिए अपना कॉलिंग कोड बदल सकते हैं। अपने सी ++ फ़ंक्शन में संरचना पैरामीटर के लिए एक अतिरिक्त संदर्भ पास करें।

typedef void (__cdecl TestFunc)(TSimpleRecord&);  

आप सी ++ पक्ष पर यह करने के लिए जा रहे हैं, तो आप सबसे अच्छा होगा स्पष्टता के लिए डेल्फी पक्ष पर भी यही बदलाव कर रही है।

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

अंगूठे के सामान्य नियम के रूप में, रिकॉर्ड पैक न करें। यदि आप ऐसा करते हैं तो आपके पास गलत संरेखण होगा जो प्रदर्शन को प्रभावित करता है। प्रश्न में रिकॉर्ड के लिए, वैसे भी कोई पैडिंग नहीं होगी क्योंकि दोनों फ़ील्ड एक ही आकार के हैं।

संबंधित मुद्दे