c# - सकत - मोबाइल नंबर को प्राइवेट नंबर बनाने के लिए तरीका




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

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

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

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

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

https://code.i-harness.com

मेरे पास डेल्फी 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 अंकों की समान संख्या (अपेक्षित परिणाम) देता है।

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


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

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


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


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

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

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

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

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

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


मैं दूसरे दिन के आसपास घूम रहा था जो सम्मेलनों को कॉल करने के बारे में जानने की कोशिश कर रहा था और मैंने विभिन्न तरीकों के बीच कन्वर्ट करने के कुछ तरीके लिखे हैं। यहां स्ट्डीकल-> फास्टकॉल के लिए एक है

typedef struct
{
    USHORT ParameterOneOffset;  // The offset of the first parameter in dwords starting at one
    USHORT ParameterTwoOffset;  // The offset of the second parmaeter in dwords starting at one
} FastCallParameterInfo;



    __declspec( naked,dllexport ) void __stdcall InvokeFast()
{
    FastCallParameterInfo paramInfo;
    int functionAddress;
    int retAddress;
    int paramOne, paramTwo;
    __asm
    {
        // Pop the return address and parameter info.  Store in memory.
        pop retAddress;
        pop paramInfo;
        pop functionAddress;

        // Check if any parameters should be stored in edx                          
        movzx ecx, paramInfo.ParameterOneOffset;     
        cmp ecx,0;
        je NoRegister;  

        // Calculate the offset for parameter one.
        movzx ecx, paramInfo.ParameterOneOffset;    // Move the parameter one offset to ecx
        dec ecx;                                    // Decrement by 1
        mov eax, 4;                                 // Put 4 in eax
        mul ecx;                                    // Multiple offset by 4

        // Copy the value from the stack on to the register.
        mov ecx, esp;                               // Move the stack pointer to ecx
        add ecx, eax;                               // Subtract the offset.
        mov eax, ecx;                               // Store in eax for later.
        mov ecx, [ecx];                             // Derefernce the value
        mov paramOne, ecx;                          // Store the value in memory.

        // Fix up stack
        add esp,4;                                  // Decrement the stack pointer
        movzx edx, paramInfo.ParameterOneOffset;    // Move the parameter one offset to edx
        dec edx;                                    // Decrement by 1
        cmp edx,0;                                  // Compare offset with zero
        je ParamOneNoShift;                         // If first parameter then no shift.

    ParamOneShiftLoop:
        mov ecx, eax;
        sub ecx, 4;
        mov ecx, [ecx]
        mov [eax], ecx;                             // Copy value over
        sub eax, 4;                                 // Go to next 
        dec edx;                                    // decrement edx
        jnz ParamOneShiftLoop;                      // Loop
    ParamOneNoShift:
        // Check if any parameters should be stored in edx                          
        movzx ecx, paramInfo.ParameterTwoOffset;     
        cmp ecx,0;
        je NoRegister;  

        movzx ecx, paramInfo.ParameterTwoOffset;    // Move the parameter two offset to ecx
        sub ecx, 2;                                 // Increment the offset by two.  One extra for since we already shifted for ecx
        mov eax, 4;                                 // Put 4 in eax
        mul ecx;                                    // Multiple by 4

        // Copy the value from the stack on to the register.
        mov ecx, esp;                               // Move the stack pointer to ecx
        add ecx, eax;                               // Subtract the offset.
        mov eax, ecx;                               // Store in eax for later.
        mov ecx, [ecx];                             // Derefernce the value
        mov paramTwo, ecx;                          // Store the value in memory.           

        // Fix up stack
        add esp,4;                                  // Decrement the stack pointer
        movzx edx, paramInfo.ParameterTwoOffset;    // Move the parameter two offset to ecx
        dec edx;                                    // Decrement by 1
        cmp edx,0;                                  // Compare offset with zero
        je NoRegister;                              // If first parameter then no shift.
    ParamTwoShiftLoop:
        mov ecx, eax;
        sub ecx, 4;
        mov ecx, [ecx]
        mov [eax], ecx;                             // Copy value over
        sub eax, 4;                                 // Go to next 
        dec edx;                                    // decrement edx
        jnz ParamTwoShiftLoop;                      // Loop


    NoRegister:
        mov ecx, paramOne;                          // Copy value from memory to ecx register
        mov edx, paramTwo;                          // 
        push retAddress;
        jmp functionAddress;
    }
}

}





dll