2013-02-12 12 views
5

मैं इसे एक प्रश्न/उत्तर के रूप में पोस्ट कर रहा हूं, क्योंकि मुझे काम करने में थोड़ी देर लग गई, और मुझे अपने समाधान पर कुछ प्रतिक्रिया नहीं होगी । गो/सीजीओ में, आप पॉइंटर के रूप में पास किए गए सी सरणी के साथ कैसे काम करते हैं?गो/सीजीओ - आप एक संकेतक के रूप में पारित सी सरणी का उपयोग कैसे करते हैं

उदाहरण के लिए, इस सी struct के साथ:

struct _GNetSnmpVarBind {      
    guint32  *oid;  /* name of the variable */ 
    gsize  oid_len; /* length of the name */ 
    ... and other fields 
}; 

मैं एक जाओ स्ट्रिंग के लिए OID क्षेत्र परिवर्तित करना चाहते हैं, मैं कैसे guint32 * सूचक के साथ काम करेंगे?

उत्तर

4

जिस तरह से मैंने इसे किया था, बाइट्स को पढ़ने के लिए (guint32 * oid_len का आकार) ढूंढना था, फिर बाइनरी की थी। बाइट्स की संख्या पर पढ़ें(), फिर टुकड़ों में बाइट्स के माध्यम से looped आकार। पीछे की ओर में आसान; कठिन हिस्सा हो रही थी प्रकार जाओ के रूप में काम रूपांतरण सी

तुलना में अधिक कड़ाई है उदाहरण के लिए यहाँ एक जाओ स्ट्रिंग के लिए guint32 * परिवर्तित (का प्रतिनिधित्व एक SNMP OID) के लिए जाओ कोड है:

func gIntArrayOidString(oid *_Ctype_guint32, oid_len _Ctype_gsize) (result string) { 
    size := int(unsafe.Sizeof(*oid)) 
    length := int(oid_len) 
    gbytes := C.GoBytes(unsafe.Pointer(oid), (_Ctype_int)(size*length)) 
    buf := bytes.NewBuffer(gbytes) 

    for i := 0; i < length; i++ { 
     var out uint32 
     if err := binary.Read(buf, binary.LittleEndian, &out); err == nil { 
      result += fmt.Sprintf(".%d", out) 
     } else { 
      return "<error converting oid>" 
     } 
    } 
    if len(result) > 1 { 
     return result[1:] // strip leading dot 
    } 
    return "<error converting oid>" 
} 

टिप्पणियाँ ?


संदर्भ: कोड gsnmpgo से है।

2

मुझे लगता है कि जीएसएनएमपी के मान जरूरी नहीं हैं कि वे छोटे-छोटे, लेकिन मूल बाइट ऑर्डर में हों। मैं सिर्फ असुरक्षित का उपयोग करता हूं। सरणी के माध्यम से पुनरावृत्त करने के लिए। जैसे

package main 

import (
    "unsafe" 
    "fmt" 
) 

var ints = [...]int32 {1, 2, 3} 

func main() { 
    var result string 
    var p *int32 = &ints[0] 
    for i := 0; i < len(ints); i++ { 
     result += fmt.Sprintf(".%d", *p) 
     p = (*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(p))+unsafe.Sizeof(*p))) 
    } 
    fmt.Println(result[1:]) 
} 
+0

धन्यवाद एक्स, मैं इसे देख लूंगा। –

3

आप एक जाओ टुकड़ा में सी सरणी परिवर्तित a tip I saw in the go wiki

Untested का उपयोग कर सकता है, लेकिन उम्मीद है कि आपको अंदाजा हो! स्लाइस को सी डेटा से अधिक लंबे समय तक रहने दें, क्योंकि यह सीधे इसमें इंगित करता है।

पिछली बार मैंने इसका इस्तेमाल किया था, मैंने अलग-अलग हिस्सों पर एक नज़र डाली थी और यह बहुत ही कुशल कोड उत्पन्न करता है।

func gIntArrayOidString(oid *_Ctype_guint32, oid_len _Ctype_gsize) (result string) { 
    var oids []uint32 
    sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&oids))) 
    sliceHeader.Cap = oid_len 
    sliceHeader.Len = oid_len 
    sliceHeader.Data = uintptr(unsafe.Pointer(oid)) 

    var result string 
    for _, value := range oids { 
     result += fmt.Sprintf(".%d", value) 
    } 
    return result[1:] 
} 
+0

यह वही है जो मैं ढूंढ रहा हूं! –

+0

2015 तक इसे विकी से हटा दिया गया था क्योंकि "इसे सुरक्षित रूप से या पोर्टेबल रूप से उपयोग नहीं किया जा सकता"। – psanford

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