2011-03-10 20 views
9

क्या एलपीटीस्ट्रेट को सीधे बीएसटी में डालना कानूनी है?क्या आप एक एलपीटीस्ट्रेट को बीएसटी में डाल सकते हैं?

मेरे understanding of BSTR के आधार पर, एक बीएसटीस्ट्रेट को एक बीस्ट्रेट में डालने से सीधे आपको एक दूषित लंबाई उपसर्ग के साथ छोड़ दिया जाएगा। उदाहरण कोड स्पष्ट रूप से बताता है कि एक स्ट्रिंग अक्षर को किसी BSTR में संग्रहीत नहीं किया जा सकता है। क्या कोई मेरे लिए पुष्टि कर सकता है कि LPTSTR/LPCTSTR को लंबाई उपसर्ग को दूषित किए बिना सीधे BSTR पर नहीं डाला जा सकता है?

संपादित करें:

मेरे भ्रम की स्थिति यह एक COM वस्तु के लिए एक कॉल में इस्तेमाल देखने से है। यह पता चला है कि COM dll संकलित करते समय, एक .tli फ़ाइल जेनरेट की जाती है जो एक मध्यवर्ती विधि बनाता है। यह विधि _bstr_t टाइप करती है। _bstr_t अपने कन्स्ट्रक्टर में LPTSTR ले सकता है, इसलिए सबकुछ सुचारू रूप से काम करता है।

उत्तर

8

काम नहीं करेगा अपने कार्यक्रम यूनिकोड है और अपने LPTSTR इसलिए एक LPWSTR है, तो आपको एक विस्तृत चरित्र स्ट्रिंग के लिए SysAllocString उपयोग कर सकते हैं एक सूचक से कन्वर्ट करने के लिए तो 210।

प्रत्यक्ष सीधी संभव नहीं है क्योंकि दोनों में अलग-अलग स्मृति प्रस्तुतियां हैं।

यदि आप सी ++ का उपयोग करते हैं, तो आप BSTR स्ट्रिंग के उपयोग को सरल बनाने के लिए _bstr_t कक्षा का उपयोग कर सकते हैं।

1

यह नहीं हो सकता है, क्योंकि LPTSTR से पहले स्मृति में चार बाइट परिणामस्वरूप BSTR की लंबाई के रूप में माना जाएगा। यह स्पॉट पर स्मृति सुरक्षा गलती का कारण बन सकता है (बहुत संभावना नहीं), लेकिन यह निश्चित रूप से BSTR में एक लंबाई के साथ परिणामस्वरूप होगा जो मूल LPTSTR की लंबाई से बड़ा हो सकता है। तो जब कोई उस से पढ़ने या लिखने का प्रयास करता है तो वे अमान्य स्मृति तक पहुंच सकते हैं।

+3

स्ट्रिंग डेटा को लंबाई के रूप में व्याख्या नहीं किया जाएगा। तुरंत बाइट्स पहले होगा। एक बीस्ट्रेट लंबाई + स्ट्रिंग संरचना के स्ट्रिंग भाग को इंगित करता है। –

+0

@ बेन: स्पष्टीकरण के लिए धन्यवाद, मुझे यह नहीं पता था। मैं तदनुसार जवाब संशोधित करूंगा। – Jon

0

नहीं, आप उन्हें सीधे नहीं डाल सकते हैं। हालांकि, आप एक स्ट्रिंग कर सकते हैं जो दोनों करता है। ए सी-स्ट्रिंग में 4-बाइट हेडर नहीं है। हालांकि, बीच में थोड़ा समान है, इसलिए यदि आपको खुद को दोनों प्रस्तुतियों की आवश्यकता है, तो एक रैपर क्लास बनाएं जो 4byte हेडर और एक नल टर्मिनेटर के साथ एक स्ट्रिंग बनाता है लेकिन बीएसआर भाग और सी-स्ट्रिंग में एक्सेसर्स को वापस कर सकता है।

यह कोड एक अपूर्ण उदाहरण के रूप में है, मैंने इसे संकलित नहीं किया है!

class YetAnotherStringType //just what the world needs 
{ 
    public: 
    YetAnotherStringType(const char *str) 
    { 
    size_t slen = strlen(str); 
    allocate(slen); 
    set_size_dword(slen); 
    copy_cstr(str, slen);  
    } 

    const char *get_cstr() const 
    { 
    return &m_data[4]; 
    } 

    const BSTR get_bstr() const 
    { 
    return (BSTR*)m_data; 
    } 

    void copy_cstr(const char *cstr, int size = -1) 
    { 
     if (size == -1) 
     size = strlen(cstr); 
     memcpy(&m_data[4], cstr, size + 1); //also copies first null terminator 
     m_data[5 + size] = 0; //add the second null terminator 
    } 

    void set_size_dword(size_t size) 
    { 
    *((unsigned int*)m_data) = size; 
    } 

    void allocate(size_t size) 
    { 
    m_data = new char[size + 6]; //enough for double terminator 
    } 

    char *m_data; 
}; 
+0

'BSTR के पास डबल-नल टर्मिनेटर है। – Jon

+0

@ जोन: आह, क्षमा करें। मैंने पृष्ठ यहां पढ़ा है और पढ़ा है कि वे नहीं करते - मैं इसे गलत तरीके से पढ़ रहा था। ऐसा लगता है कि हेडर में शून्य टर्मिनेटर नहीं है (!?) – Luther

+0

पहले से ही एक स्ट्रिंग है जो दोनों करता है: '' –

1

एक LPTSTR एक चार सरणी के लिए सूचक है (या TCHAR सटीक होना करने के लिए) BSTR एक स्ट्रक्चरल (या मिश्रित डेटा) है * लंबाई उपसर्ग * डेटा स्ट्रिंग * टर्मिनेटर

से मिलकर बनता है इसलिए कास्टिंग

0

नहीं, आप नहीं कर सकते - अगर कोड यह मानता है कि यह बीएसआर SysStringLen() पर कॉल करता है तो यह अपरिभाषित व्यवहार में चलेगा क्योंकि यह फ़ंक्शन कुछ कार्यान्वयन-विशिष्ट सेवा डेटा पर निर्भर करता है।

0

आप नहीं डाले जा सकते हैं, आपको कन्वर्ट करना होगा। आप आसानी से ऐसा करने में सहायता के लिए अंतर्निहित कंपाइलर आंतरिक _bstr_t (comutil.h से) का उपयोग कर सकते हैं। नमूना:

#include <Windows.h> 
#include <comutil.h> 

#pragma comment(lib, "comsuppwd.lib") 

int main() 
{ 
    LPTSTR p = "Hello, String"; 
    _bstr_t bt = p; 
    BSTR bstr = bt; 
    bstr; 
} 
+0

@ जॉन डिबलिंग: हाय। क्या उदाहरण मैंने काम नहीं किया? यदि नहीं, तो क्या आप समझा सकते हैं कृपया क्यों? – Luther

+1

@ लूथर: दो चीजें। 1) एमएस पहले से ही आपके लिए ऐसा करने के लिए कक्षा प्रदान करने पर कोड का एक गुच्छा क्यों लिखता है (_bstr_t)? 2) आपके द्वारा लिखे गए कोड काम कर सकते हैं या नहीं कर सकते हैं; मुझे यकीन नहीं है। आपको एक BSTR बनाने के लिए 'SysAllocString' को कॉल करना होगा, लेकिन आप स्वयं को बनाने के लिए एक BSTR के आंतरिक-कार्यकलापों के ज्ञान का उपयोग करने का प्रयास कर रहे हैं। इसके अलावा, एक बीस्ट्रेट का स्ट्रिंग हिस्सा यूनिकोड है।तुम्हारा, मुझे लगता है, नहीं है। –

+0

@ जॉन डिबलिंग: प्रतिक्रिया के लिए धन्यवाद। मैं पहिया को फिर से शुरू करने की कोशिश नहीं कर रहा हूं, कोड सिर्फ एक बिंदु को चित्रित करने के लिए था। यहां हमारा आदमी एक बीएसटी बनाने और प्रतिलिपि बनाने के बजाय कास्टिंग के बारे में पूछ रहा था। उनके पास पुनर्निर्माण के बजाय कास्ट करने का अच्छा कारण हो सकता है (तंग स्मृति आवश्यकताओं, आंतरिक लूप के अंदर कई कॉल, ढेर आदि को छूना नहीं चाहते हैं) और जिस श्रेणी में मैंने स्केच किया है उसे * प्राप्त करना चाहिए। यदि BSTRs यूनीकोड ​​हैं, तो char * को wchar_t * के साथ बदलें। कभी-कभी अपने आप को थोड़ा सा कोड लिखना सबसे अच्छा होता है यदि मानक तरीके नौकरी नहीं करते हैं, जिस तरह से आप उन्हें चाहते हैं। – Luther

0

आम तौर पर कोई बोल रहा है, लेकिन वहाँ उन्हें सहायक वर्गों और मैक्रो (नीचे देखें) के माध्यम से कुछ हद तक संगत बनाने के लिए तरीके हैं।

मुख्य कारण एक 1: 1 मानचित्रण संभव कभी नहीं होगा है कि एक BSTR (और फलस्वरूप CComBSTR स्ट्रिंग में '\0' हो सकते हैं, क्योंकि अंतत: यह एक गिना स्ट्रिंग प्रकार है


आपका सबसे अच्छा। चुनाव जब सी का उपयोग कर ++ भी ध्यान रखें कि प्रलेखन (MSDN) का कहना है BSTR उचित के स्थान पर ATL वर्ग CComBSTR के लिए जाने के लिए होगा। या तो मामले में आप ATL के उपयोग/MFC रूपांतरण मैक्रो CW2A और दोस्तों के कर सकते हैं।

:

और BSTR से तार को बदलने की सिफारिश की जिस तरह से CComBSTR वर्ग का प्रयोग है। BSTR में कनवर्ट करने के लिए, मौजूदा स्ट्रिंग को CComBSTR के कन्स्ट्रक्टर को पास करने के लिए पास करें। बीएसआर से को परिवर्तित करने के लिए, COLE2 [C] गंतव्य प्रकार टाइप करें [EX], जैसे COLE2T

... जो आपके उपयोग के मामले पर लागू होता है।

कृपया जॉन डिबलिंग के वैकल्पिक विकल्प के लिए उत्तर देखें (_bstr_t)।

4

आप BSTR रों रूप LPCTSTR रों पारित तो आप पाएंगे कि आप बेतरतीब ढंग से किसी भी इंटरॉप मार्शलिंग कोड आप के पास मिल को उड़ाने होगा करने की कोशिश कर रहे हैं। Marshalling LPCTSTR के लिए 4 बाइट उपसर्ग (जो यादृच्छिक डेटा है) खींच जाएगा और स्ट्रिंग को मार्शल कोशिश करें।

आप पाएंगे कि 4 बाइट उपसर्ग आपके बफर से पहले स्टैक सामग्री या इससे पहले स्ट्रिंग से बेहतर चरित्र डेटा बन जाता है। इसके बाद आप डेटा के मार्शल मेगाबाइट करने की कोशिश करेंगे ... :-)

CComBSTR रैपर का उपयोग करें और .Detach() उपयोग करें यदि आप BSTR सूचक रखने की जरूरत है।

अच्छा बनें अगर संकलक इस पर एक चेतावनी फैलता है।

+0

बस इसके द्वारा काट दिया गया, तीन एल "माई स्ट्रिंग" पैरामीटर को पास करने के लिए .NET COM विधि को 3 BSTRs की उम्मीद है और केवल एक इंटरऑप marshalling बच गया। कंपाइलर वीएस 2008/डब्ल्यू 4 – Lallen

+0

से कोई चेतावनी नहीं है 4 बाइट उपसर्ग बीएसटी की लंबाई का प्रतिनिधित्व करता है। – lsalamon

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