2009-03-17 7 views
6

मैं एक सी एपीआई (एक देशी विन डीएल) के लिए सी # पी/इनवोक रैपर लिखने की कोशिश कर रहा हूं, और आम तौर पर यह ठीक काम कर रहा है। एकमात्र अपवाद एक विशिष्ट विधि है जो सी कोड में पैरामीटर के रूप में एक संरचना लेता है। फ़ंक्शन को किसी भी अपवाद के बिना बुलाया जाता है, लेकिन यह झूठा रिटर्न देता है कि निष्पादन में कुछ विफल रहा है।सी # पी/संरचना की समस्या को शामिल करें

एपीआई हैडर शामिल विधि और structs फ़ाइल में निम्न प्रकार परिभाषित कर रहे हैं:

public const int MAX_ICE_MS_TRACK_LENGTH = 256; 

[StructLayout(LayoutKind.Sequential)] 
public class MSTrackData { 
    public UInt32 nLength; 
    public readonly Byte[] TrackData = new byte[MAX_ICE_MS_TRACK_LENGTH]; 
} 

[DllImport("ICE_API.dll", CharSet = CharSet.Auto, SetLastError = true)] 
public static extern bool EncodeMagstripe(IntPtr hDC, 
        [In]ref MSTrackData pTrack1, 
        [In]ref MSTrackData pTrack2, 
        [In]ref MSTrackData pTrack3, 
        [In]ref MSTrackData reserved); 
:

#define MAX_ICE_MS_TRACK_LENGTH 256 
typedef struct tagTRACKDATA 
{ 
    UINT nLength; 
    BYTE TrackData[MAX_ICE_MS_TRACK_LENGTH]; 
} TRACKDATA, FAR* LPTRACKDATA; 
typedef const LPTRACKDATA LPCTRACKDATA; 

BOOL ICEAPI EncodeMagstripe(HDC /*hDC*/, 
      LPCTRACKDATA /*pTrack1*/, 
      LPCTRACKDATA /*pTrack2*/, 
      LPCTRACKDATA /*pTrack3*/, 
      LPCTRACKDATA /*reserved*/); 

मैं/एक सी # पी बनाने के लिए निम्नलिखित कोड का उपयोग कर आवरण आह्वान के प्रयास किए हैं

CardApi.MSTrackData trackNull = null; 
CardApi.MSTrackData track2 = new CardApi.TrackData(); 
byte[] trackBytes = Encoding.ASCII.GetBytes(";?"); 
track2.nLength = (uint)trackBytes.Length; 
Buffer.BlockCopy(trackBytes, 0, track2.TrackData, 0, trackBytes.Length); 

if (!CardApi.EncodeMagstripe(hDC, ref trackNull, ref track2, ref trackNull, ref trackNull)) { 
    throw new ApplicationException("EncodeMagstripe failed", Marshal.GetLastWin32Error()); 
} 

गु:

तो मैं निम्नलिखित सी # कोड का उपयोग कर EncodeMagstripe विधि को लागू करने की कोशिश एप्लिकेशनएक्सप्शन को फेंकने का कारण बनता है, और त्रुटि कोड 801 है जो दस्तावेज़ीकरण के अनुसार है "डेटा में चयनित ट्रैक 2 प्रारूप के लिए बहुत से वर्ण शामिल हैं।"। हालांकि चयनित ट्रैक प्रारूप में 39 अक्षरों की अनुमति होनी चाहिए (मैंने छोटे तारों को भी आजमाया है)।

मुझे लगता है कि एमएसटीआरडीटा परिभाषा में मैंने कुछ गलत किया है, लेकिन मुझे यह नहीं पता कि यह क्या हो सकता है। क्या किसी के पास कोई सुझाव है?

उत्तर

5

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

public const int MAX_ICE_MS_TRACK_LENGTH = 256; 

[StructLayout(LayoutKind.Sequential)] 
public class MSTrackData { 
    public UInt32 nLength; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] 
    public Byte[] TrackData = new byte[MAX_ICE_MS_TRACK_LENGTH]; 
} 

[DllImport("ICE_API.dll", CharSet = CharSet.Auto, SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
public static extern bool EncodeMagstripe(IntPtr hDC, 
       [In] MSTrackData pTrack1, 
       [In] MSTrackData pTrack2, 
       [In] MSTrackData pTrack3, 
       [In] MSTrackData reserved); 
+0

ICEAPI WINAPI को संदर्भित करता है, इसलिए मैंने DllImport विशेषता में "कॉलिंग कन्वेंशन = कॉलिंग कन्वेंशन। विनापी" भी सेट किया है। आपके सुझाव को लागू करने के बाद, कॉल पूरी तरह से काम करता था :-) आपको बहुत बहुत धन्यवाद :-) –

2

मैं नए के साथ नहीं बाइट सरणी को परिभाषित करेगा, लेकिन सही आकार आरंभ करने के बजाय निम्नलिखित कोड का उपयोग करें:

[MarshalAs (UnmanagedType.byValTSt, SizeConst = 256)] सार्वजनिक केवल पढ़ने के लिए बाइट [] TrackData;

मैंने इसे अतीत में चार सरणी पर सफलतापूर्वक उपयोग किया है।

+0

कि UnmanagedType.ByValArray नहीं होना चाहिए: दोनों के साथ EncodeMagstripe और ReadMagstripe - यहाँ कार्यान्वयन है कि अंततः मेरे लिए काम किया है? – OregonGhost

+0

चूंकि यह एक बाइट सरणी है और स्ट्रिंग नहीं है, इसलिए यह संभवतः [मार्शलएएस (UnmanagedType.ByValArray, SizeConst = 256)] हालांकि इससे कोई फर्क नहीं पड़ता है, और मुझे अभी भी वही त्रुटि मिलती है। –

+0

ओरेगॉनहोस्ट सही है - सुनिश्चित नहीं है कि यह कोई फर्क पड़ता है - यहां इसका परीक्षण नहीं कर सकता ... – weismat

1

मुझे लगता है कि समस्या की तरह यह है कि आप संदर्भ द्वारा संदर्भ पारित कर रहे हैं। चूंकि MSTrackData एक वर्ग (यानी संदर्भ प्रकार) है, संदर्भ द्वारा इसे पास करने से पॉइंटर-टू-पॉइंटर पास करना है।

आपकी प्रबंधित प्रोटोटाइप बदलें:

public static extern bool EncodeMagstripe(IntPtr hDC, 
        MSTrackData pTrack1, 
        MSTrackData pTrack2, 
        MSTrackData pTrack3, 
        MSTrackData reserved); 

MSDN लेख के बारे में passing structures देखें।

+0

हां, अच्छा है कि मार्शलिंग कितनी स्वचालित है। लेकिन जॉनी को एमएसट्रैकडाटा के 1 के लिए न्यूल पास करने की भी आवश्यकता है। –

+0

और चूंकि एमएसटीआरडीटाटा उनके उदाहरण में एक संदर्भ प्रकार है, इसलिए यह शून्य होने के लिए तुच्छ है। –

0

मुझे लगभग एक ही समस्या थी - लेकिन ReadMagstripe के साथ। और EncodeMagstripe के लिए यहां प्रदान किया गया समाधान ReadMagstripe के लिए काम नहीं किया था! मुझे लगता है कि यह काम नहीं करने का कारण था कि ReadMagstripe को डेटा को TRACKDATA संरचना/कक्षा में वापस करना है, जबकि EncodeMagstripe केवल डेटा को डीएलएल में पास करता है और TRACKDATA में डेटा को बदलने की आवश्यकता नहीं है।

public const int MAX_ICE_MS_TRACK_LENGTH = 256; 
    [StructLayout(LayoutKind.Sequential)] 
    public struct TRACKDATA 
    { 
     public UInt32 nLength; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 
     public string szTrackData; 
    } 


    [DllImport("ICE_API.dll", EntryPoint="[email protected]", CharSet=CharSet.Auto, 
     CallingConvention=CallingConvention.Winapi, SetLastError=true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    public static extern bool ReadMagstripe(int hdc, ref TRACKDATA ptrack1, ref TRACKDATA ptrack2, 
     ref TRACKDATA ptrack3, ref TRACKDATA reserved); 

    [DllImport("ICE_API.dll", EntryPoint="[email protected]", CharSet=CharSet.Auto, 
     CallingConvention = CallingConvention.Winapi, SetLastError=true)] 
    public static extern bool EncodeMagstripe(int hdc, [In] ref TRACKDATA ptrack1, [In] ref TRACKDATA ptrack2, 
     [In] ref TRACKDATA ptrack3, [In] ref TRACKDATA reserved); 


/* 
     .... 
*/ 


    private void EncodeMagstripe() 
    { 
     ICE_API.TRACKDATA track1Data = new ICE_API.TRACKDATA(); 
     ICE_API.TRACKDATA track2Data = new ICE_API.TRACKDATA(); 
     ICE_API.TRACKDATA track3Data = new ICE_API.TRACKDATA(); 
     ICE_API.TRACKDATA reserved = new ICE_API.TRACKDATA(); 

     //if read magstripe 
     bool bRes = ICE_API.ReadMagstripe(printer.Hdc, ref track1Data, ref track2Data, 
      ref track3Data, ref reserved); 

     //encode magstripe 
     if (bRes) 
     { 
      track2Data.szTrackData = "1234567890"; 
      track2Data.nLength = 10; 

      bRes = ICE_API.EncodeMagstripe(printer.Hdc, ref track1Data, ref track2Data, ref track3Data, ref reserved); 
     } 
    } 
+1

मेरा उपरोक्त समाधान ReadMagstripe के लिए ठीक काम करेगा लेकिन चूंकि यह फ़ंक्शन MSTrackData संरचनाओं में डेटा को प्रत्येक MSTrackData पर [इन] विशेषता देता है पैरामीटर को [इन, आउट] में बदलना होगा। –

+0

ओह मैं देखता हूं ... मुझे नहीं पता था कि इन अटूट्यूट्स का उद्देश्य क्या है। – Evgeny

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