c# सकत सी#से डेल्फी डीएलएल को कॉल करने से अप्रत्याशित परिणाम उत्पन्न होता है




मोबाइल नंबर को प्राइवेट नंबर बनाने के लिए तरीका (6)

मैंने ऐसा कभी नहीं किया है, लेकिन अपना कोड बदलने का प्रयास करें:

function CreateCode(SerialID : String;
    StartDateOfYear, YearOfStartDate, YearOfEndDate, DatePeriod : Word;
    CodeType,RecordNumber,StartHour,EndHour : Byte) : PChar; stdcall;
    external 'CreateCodeDLL.dll';

अतिरिक्त stdcall नोट करें

संपादित करें 2: जैसा कि आप अन्य जवाबों से देख सकते हैं आपको इसके बाद के संस्करण में परिवर्तन करना होगा या आवरण डीएलएल लिखना होगा जो एक ही काम करता है।

मेरे पास डेल्फी DLL है जो मैंने नहीं लिखा था, लेकिन सी # एएसपी.नेट 3.5 ऐप से कॉल करने की आवश्यकता है। डेवलपर से मिली फ़ंक्शन परिभाषा यहां दी गई है:

function CreateCode(SerialID : String; 
    StartDateOfYear, YearOfStartDate, YearOfEndDate, DatePeriod : Word; 
    CodeType,RecordNumber,StartHour,EndHour : Byte) : PChar;
    external 'CreateCodeDLL.dll';

और यहाँ मेरा सी # कोड है:

[DllImport( "CreateCodeDLL.dll", 
    CallingConvention = CallingConvention.StdCall, 
    CharSet=CharSet.Ansi)]
public static extern IntPtr CreateCode( string SerialID,
                                        UInt16 StartDateOfYear,
                                        UInt16 YearOfStartDate,
                                        UInt16 YearOfEndDate,
                                        UInt16 DatePeriod,
                                        Byte CodeType,
                                        Byte RecordNumber,
                                        Byte StartHour,
                                        Byte EndHour);

और अंत में, इस विधि से मेरा कॉल:

//The Inputs 
String serialID = "92F00000B4FBE";
UInt16 StartDateOfYear = 20;
UInt16 YearOfStartDate = 2009;
UInt16 YearOfEndDate = 2009;
UInt16 DatePeriod = 7;
Byte CodeType = 1;
Byte RecordNumber = 0;
Byte StartHour = 15;
Byte EndHour = 14;            

// The DLL call
IntPtr codePtr = CodeGenerator.CreateCode(serialID, StartDateOfYear, 
                YearOfStartDate, YearOfEndDate, DatePeriod, CodeType, 
                RecordNumber, StartHour, EndHour);

// Take the pointer and extract the code in a string
String code = Marshal.PtrToStringAnsi(codePtr);  

हर बार जब मैं इस सटीक कोड को फिर से संकलित करता हूं और इसे चलाता हूं, तो यह एक अलग मान देता है अपेक्षित मूल्य संख्याओं के एक 10 अंकों वाला कोड है। लौटा मूल्य वास्तव में 12 अंक है।

जानकारी का अंतिम महत्वपूर्ण हिस्सा यह है कि मेरे पास एक परीक्षा है। EXE जिसमें GUI है जो मुझे DLL का परीक्षण करने की अनुमति देता है। .EXE का उपयोग करते हुए प्रत्येक परीक्षा में 10 अंकों की समान संख्या (अपेक्षित परिणाम) देता है।

तो, मुझे विश्वास करना होगा कि मैंने अपने कॉल को डीएलएल को गलत तरीके से घोषित किया है। विचार?


वापसी मूल्य एक और समस्या हो सकती है यह शायद या तो स्मृति रिसाव है (वे ढेर पर बफर आवंटित करते हैं और यह कभी मुफ्त नहीं होता है) या पहले से मुक्त मेमोरी तक पहुंच (वे पीसीर को स्थानीय स्ट्रिंग वेरिएबल का उपयोग करते हैं)।

रिटर्निंग स्ट्रिंग (या सामान्य में वैरिएबल आकार के डेटा) फ़ंक्शन से दूसरे मॉड्यूल में सामान्य रूप से समस्याग्रस्त है।

एक समाधान (Winapi द्वारा उपयोग किया जाता है) कॉलर को बफ़र और इसके आकार में पास करने की आवश्यकता होती है। उस का नुकसान यह है कि यदि बफर बहुत छोटा है तो फ़ंक्शन विफल हो जाता है, और कॉलर को इसे फिर से एक बड़ा बफर के साथ बुलाया जाना चाहिए।

एक अन्य संभावित समाधान फ़ंक्शन में बफर से बफर को आवंटित करना है और उसे वापस करना है। फिर आपको किसी अन्य फ़ंक्शन को निर्यात करना होगा जो कॉलर को आवंटित स्मृति को फिर से मुक्त करने के लिए उपयोग करना चाहिए। यह सुनिश्चित करता है कि स्मृति को उसी रनटाइम से मुक्त किया गया है जो इसे आवंटित किया गया था।

अलग (बोरलैंड नहीं) भाषाओं के बीच एक (डेल्फी) स्ट्रिंग पैरामीटर पास करना संभवतः असंभव है और यहां तक ​​कि डेल्फी मॉड्यूल के बीच आप दोनों मॉड्यूल मेमोरी मैनेजर के समान उदाहरण का उपयोग सुनिश्चित करने के लिए। आम तौर पर इसका मतलब है कि सभी मॉड्यूल के लिए पहला उपयोग के रूप में "शेयरमैन का उपयोग करें" जोड़ने का मतलब है। एक और अंतर कॉलिंग कन्वेंशन "रजिस्टर" है जो एक फास्टकॉल सम्मेलन है, लेकिन फास्टकॉल एमएस कंपाइलर्स के उपयोग के समान नहीं है।

एक पूरी तरह से अलग समाधान डेल्फी डीएलएल के डेल्फी डीएलएल कंपिलर में से एक के साथ पुनः कंपाइलिंग हो सकता है। कितना काम उनके कोड पर निर्भर करता है


डेल्फी डिफ़ॉल्ट रूप से तथाकथित फास्टकॉल कॉलिंग सम्मेलन का उपयोग करता है। इसका मतलब यह है कि संकलक सीपीयू रजिस्टरों में किसी फ़ंक्शन के पैरामीटर को पार करने की कोशिश करता है और यदि केवल रिक्त रजिस्टरों के मुकाबले अधिक पैरामीटर हैं तो स्टैक का उपयोग करता है। उदाहरण के लिए डेल्फी एक समारोह में पहले तीन पैरामीटर के लिए (ईएक्स, ईडीएक्स, ईसीएक्स) का उपयोग करता है
आपके सी # कोड में आप वास्तव में stdcall कॉलिंग सम्मेलन का उपयोग कर रहे हैं, जो ढेर के माध्यम से पैरामीटर को पारित करने के लिए कंपाइलर को निर्देशित करता है (रिवर्स ऑर्डर में, यानी आखिरी परम पहले धकेल दिया गया है) और कैली स्टैप को ढेर करने दें।
इसके विपरीत, C / C + कंपाइलर्स द्वारा उपयोग किए जाने वाले cdecl कॉलिंग कॉलर को स्टैक को पुश करने के लिए मजबूर करता है।
बस सुनिश्चित करें कि आप दोनों पक्षों पर एक ही कॉलिंग कन्वेंशन का उपयोग कर रहे हैं Stdcall का ज्यादातर उपयोग किया जाता है क्योंकि इसका उपयोग लगभग हर जगह किया जा सकता है और हर संकलक द्वारा समर्थित है (Win32 API भी इस सम्मेलन का उपयोग करते हैं)।
नोट करें कि fastcall .NET द्वारा समर्थित नहीं है।


jn सही है फ़ंक्शन प्रोटोटाइप, जैसा कि दिया जाता है, को सी # से आसानी से सीधे नहीं कहा जा सकता क्योंकि यह डेल्फी के register कॉलिंग सम्मेलन में है। आपको या तो इसके लिए एक stdcall फ़ंक्शन लिखना होगा - शायद किसी अन्य DLL में यदि आपके पास स्रोत नहीं है - या आपको ऐसे लोगों को प्राप्त करने की आवश्यकता है जो कॉलिंग कॉन्फ़्रेंस को stdcall परिवर्तित करने के लिए फ़ंक्शन को बनाए रखना stdcall

अद्यतन: मैं यह भी देख रहा हूं कि पहला तर्क डेल्फी स्ट्रिंग है यह ऐसा कुछ नहीं है जो C # या तो आपूर्ति कर सकता है यह बजाय एक पीसीर होना चाहिए। इसके अलावा, यह स्पष्ट होना महत्वपूर्ण है कि फ़ंक्शन एएनडी या यूनिकोड है या नहीं; अगर DLL को डेल्फी 2009 (या बाद में) के साथ लिखा गया है, तो यह यूनिकोड है, अन्यथा यह Ansi है


डेल्फी में एक COM आवरण बनाएं और इंटरॉप के माध्यम से अपने सी # कोड में कॉल करें। वॉइला .. सी # या किसी भी अन्य भविष्य के प्लेटफॉर्म से उपयोग करने में आसान है।


जब आप उन्हें कॉलिंग कन्वेंशन बदलने के लिए कह रहे हैं, तो आपको उन्हें पहले पैरामीटर बदलने के लिए कह देना चाहिए ताकि यह "स्ट्रिंग" नहीं है उन्हें पॉइंट को एक (नल-टर्मिनेटेड) चार या वाइटरचर सरणी के बजाय उपयोग करने के लिए ले जाएं डीएलएल मापदंडों के रूप में डेल्फी स्ट्रिंग्स का उपयोग करना क्रॉस-लैंग्वेज संगतता हासिल करने की कोशिश की गयी जटिलता के बिना भी एक बुरा विचार है। इसके अलावा स्ट्रिंग वेरिएबल या तो एएससीआईआई या यूनिकोड सामग्री के आधार पर होगा जो वे डेल्फी का उपयोग कर रहे हैं।







dll