2013-11-01 8 views
5

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

मैं डीएल को कॉल करने के लिए मुक्ति का उपयोग कर रहा हूं, जैसा कि here प्रदर्शित किया गया है। मेरे बुनियादी आवश्यकताओं हैं:

  • मैं बाइट सरणी
  • मैं बाइट सरणी बनाने के लिए आवश्यक आकार दिया हूँ
  • मैं बाइट सरणी के लिए सूचक मिल चाहिए
  • मैं तो सूचक पारित विंडोज़ डीएल

मैं यह नहीं समझ सकता कि कैसे एक बाइट सरणी बनाने के लिए, और इसे पॉइंटर प्राप्त करें। यह स्पष्ट रूप से एक असुरक्षित ऑपरेशन है, और unsafe लाइब्रेरी मुझे मदद करनी चाहिए, लेकिन मुझे पहले स्थान पर गतिशील-लंबाई बाइट सरणी बनाने में सक्षम होना चाहिए। "मेक" के साथ एक टुकड़ा बनाना मेरी मदद नहीं करता है, जब तक कि मैं स्लाइस की बैकिंग सरणी में पॉइंटर नहीं प्राप्त कर सकता।

क्या किसी और को इसका सामना करना पड़ा है या कोई विचार है?

उत्तर

3

मुझे लगता है कि syscall.ComputerName कार्यान्वयन https://golang.org/src/syscall/syscall_windows.go#395 एक अच्छा उदाहरण होगा। यह uint16s का उपयोग करता है, बाइट्स नहीं, लेकिन अन्यथा ...

आपके मामले में यह ptr := &myslice[0] होगा।

एलेक्स

+1

शानदार, यह एक आकर्षण की तरह काम करता है। 'ptr: = और myslice [0]' – chowey

3

अच्छी तरह से मुझे एक सकल समाधान मिला। स्पष्ट रूप से structure of a slice में बैकिंग बाइट सरणी, बैकिंग बाइट सरणी की लंबाई, और फिर बैकिंग बाइट सरणी की क्षमता के लिए एक सूचक शामिल है।

मुझे केवल बाइट सरणी के सूचक में दिलचस्पी है, इसलिए मुझे केवल स्लाइस के आंतरिक डेटा के पहले सदस्य की आवश्यकता है।

गो unsafe.Pointer एक असुरक्षित सूचक के लिए एक टुकड़ा नहीं डालेगा, लेकिन यह एक टुकड़ा को एक असुरक्षित सूचक के रूप में एक टुकड़ा डालेगा। चूंकि मैं किसी भी पुराने प्रकार के पॉइंटर को एक असुरक्षित पॉइंटर डाल सकता हूं, इसलिए मैं इसे पॉइंटर-टू-ए-पॉइंटर पर डाल सकता हूं, जो स्लाइस के आंतरिक डेटा के पहले सदस्य को पुनः प्राप्त करता है।

यहां एक कामकाजी उदाहरण है। मैं uintptr चाहता था लेकिन आप इसे किसी भी सूचक प्रकार में डाल सकते हैं।

package main 

import (
    "fmt" 
    "unsafe" 
) 

func main() { 
    // Arbitrary size 
    n := 4 

    // Create a slice of the correct size 
    m := make([]int, n) 

    // Use convoluted indirection to cast the first few bytes of the slice 
    // to an unsafe uintptr 
    mPtr := *(*uintptr)(unsafe.Pointer(&m)) 

    // Check it worked 
    m[0] = 987 
    // (we have to recast the uintptr to a *int to examine it) 
    fmt.Println(m[0], *(*int)(unsafe.Pointer(mPtr))) 
} 

यदि आप एक *int बजाय चाहता था, आप mPtr := *(**int)(unsafe.Pointer(&m))

कर सकता है यह रूप में लंबे समय के रूप में एक टुकड़ा इस आंतरिक डेटा संरचना को बनाए रखता है काम करता है। मैं निश्चित रूप से एक अधिक मजबूत समाधान के लिए खुला हूं जो गो के आंतरिक की संरचना पर निर्भर नहीं है।

+2

मीटर के समर्थन सरणी के पहले तत्व के लिए सूचक: = बनाने ([] पूर्णांक, 10) टुकड़ा है और मीटर [0]। – alex

+0

मेरा बुरा। मैंने कोशिश की थी कि मैंने क्या सोचा था और एम [0] पहले था, और एम [0] की एक प्रतिलिपि के लिए एक सूचक प्राप्त कर रहा था। जाहिर है मैंने कुछ गलत किया, क्योंकि अब कोशिश कर रहा है, यह ठीक काम करता है। – chowey

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