नई गो भाषा में, मैं C ++ कोड कैसे कह सकता हूं? दूसरे शब्दों में, मैं अपनी C ++ कक्षाओं को कैसे लपेट सकता हूं और उन्हें गो में उपयोग कर सकता हूं?
नई गो भाषा में, मैं C ++ कोड कैसे कह सकता हूं? दूसरे शब्दों में, मैं अपनी C ++ कक्षाओं को कैसे लपेट सकता हूं और उन्हें गो में उपयोग कर सकता हूं?
जवाबों:
अपडेट: मैंने एक छोटे परीक्षण C ++ क्लास को गो के साथ लिंक करने में सफलता पाई है
यदि आप एक C इंटरफ़ेस के साथ C ++ कोड लपेटते हैं, तो आपको अपनी लाइब्रेरी को cgo के साथ कॉल करने में सक्षम होना चाहिए (gmp का उदाहरण देखें $GOROOT/misc/cgo/gmp
)।
मुझे यकीन नहीं है कि अगर सी ++ में एक वर्ग का विचार वास्तव में गो में अभिव्यक्त होता है, क्योंकि इसमें विरासत नहीं है।
यहाँ एक उदाहरण है:
मेरे पास एक C ++ वर्ग है जिसे इस प्रकार परिभाषित किया गया है:
// foo.hpp
class cxxFoo {
public:
int a;
cxxFoo(int _a):a(_a){};
~cxxFoo(){};
void Bar();
};
// foo.cpp
#include <iostream>
#include "foo.hpp"
void
cxxFoo::Bar(void){
std::cout<<this->a<<std::endl;
}
जो मैं गो में उपयोग करना चाहता हूं। मैं सी इंटरफेस का उपयोग करूँगा
// foo.h
#ifdef __cplusplus
extern "C" {
#endif
typedef void* Foo;
Foo FooInit(void);
void FooFree(Foo);
void FooBar(Foo);
#ifdef __cplusplus
}
#endif
(मैं void*
एक सी संरचना के बजाय का उपयोग करता हूं ताकि कंपाइलर फू के आकार को जानता है)
कार्यान्वयन है:
//cfoo.cpp
#include "foo.hpp"
#include "foo.h"
Foo FooInit()
{
cxxFoo * ret = new cxxFoo(1);
return (void*)ret;
}
void FooFree(Foo f)
{
cxxFoo * foo = (cxxFoo*)f;
delete foo;
}
void FooBar(Foo f)
{
cxxFoo * foo = (cxxFoo*)f;
foo->Bar();
}
सभी के साथ किया, जाओ फ़ाइल है:
// foo.go
package foo
// #include "foo.h"
import "C"
import "unsafe"
type GoFoo struct {
foo C.Foo;
}
func New()(GoFoo){
var ret GoFoo;
ret.foo = C.FooInit();
return ret;
}
func (f GoFoo)Free(){
C.FooFree(unsafe.Pointer(f.foo));
}
func (f GoFoo)Bar(){
C.FooBar(unsafe.Pointer(f.foo));
}
जो मेकफाइल मैंने इस्तेमाल किया था, वह था:
// makefile
TARG=foo
CGOFILES=foo.go
include $(GOROOT)/src/Make.$(GOARCH)
include $(GOROOT)/src/Make.pkg
foo.o:foo.cpp
g++ $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $<
cfoo.o:cfoo.cpp
g++ $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $<
CGO_LDFLAGS+=-lstdc++
$(elem)_foo.so: foo.cgo4.o foo.o cfoo.o
gcc $(_CGO_CFLAGS_$(GOARCH)) $(_CGO_LDFLAGS_$(GOOS)) -o $@ $^ $(CGO_LDFLAGS)
इसके साथ परीक्षण करने का प्रयास करें:
// foo_test.go
package foo
import "testing"
func TestFoo(t *testing.T){
foo := New();
foo.Bar();
foo.Free();
}
आपको साझा लाइब्रेरी स्थापित करने की आवश्यकता होगी, फिर मेक टेस्ट चलाएं। अपेक्षित उत्पादन है:
gotest
rm -f _test/foo.a _gotest_.6
6g -o _gotest_.6 foo.cgo1.go foo.cgo2.go foo_test.go
rm -f _test/foo.a
gopack grc _test/foo.a _gotest_.6 foo.cgo3.6
1
PASS
go test
बिना काम करना चाहिए
लगता है कि वर्तमान में SWIG इसके लिए सबसे अच्छा समाधान है:
http://www.swig.org/Doc2.0/Go.html
यह वंशानुक्रम का समर्थन करता है और यहां तक कि गो संरचना के साथ C ++ वर्ग को उप-वर्ग करने की अनुमति देता है, जब ओवरराइड विधियों को C ++ कोड में कहा जाता है, तो गो कोड निकाल दिया जाता है।
Go FAQ में C ++ के बारे में अनुभाग अपडेट किया गया है और अब SWIG का उल्लेख करता है और अब यह नहीं कहता है " क्योंकि गो कचरा एकत्र है, ऐसा करने के लिए वह नासमझ होगा, कम से कम भोलेपन से "।
आप अक्सर पूछे जाने वाले प्रश्न में जो कुछ भी पढ़ते हैं उससे आप अभी तक नहीं कर सकते हैं :
क्या कार्यक्रम C / C ++ प्रोग्राम के साथ लिंक करते हैं?
दो गो संकलक कार्यान्वयन, gc (6g प्रोग्राम और मित्र) और gccgo हैं। Gc एक अलग कॉलिंग कन्वेंशन और लिंकर का उपयोग करता है और इसलिए इसे केवल उसी कन्वेंशन का उपयोग करके C प्रोग्राम्स के साथ जोड़ा जा सकता है। ऐसा C कंपाइलर है लेकिन C ++ कंपाइलर नहीं है। Gccgo एक GCC फ्रंट-एंड है जो देखभाल के साथ GCC- संकलित C या C ++ प्रोग्राम के साथ जोड़ा जा सकता है।
कॉगो प्रोग्राम गो कोड से सी लाइब्रेरी की सुरक्षित कॉलिंग की अनुमति देने के लिए "विदेशी फ़ंक्शन इंटरफ़ेस" के लिए तंत्र प्रदान करता है। SWIG इस क्षमता को C ++ पुस्तकालयों तक पहुंचाता है।
Go1.2 + के रूप में, cgo C ++ कोड को स्वचालित रूप से शामिल और संकलित करता है:
मैंने स्कॉट वेल्स के उत्तर के आधार पर निम्नलिखित उदाहरण बनाया है । मैंने इसे macOS High Sierra 10.13.3 रनिंग go
वर्जन में टेस्ट किया है go1.10 darwin/amd64
।
(1) कोड library.hpp
, C ++ API जिसे हम कॉल करना चाहते हैं।
#pragma once
class Foo {
public:
Foo(int value);
~Foo();
int value() const;
private:
int m_value;
};
(2) कोड library.cpp
, C ++ कार्यान्वयन।
#include "library.hpp"
#include <iostream>
Foo::Foo(int value) : m_value(value) {
std::cout << "[c++] Foo::Foo(" << m_value << ")" << std::endl;
}
Foo::~Foo() { std::cout << "[c++] Foo::~Foo(" << m_value << ")" << std::endl; }
int Foo::value() const {
std::cout << "[c++] Foo::value() is " << m_value << std::endl;
return m_value;
}
(3) library-bridge.h
एक C
एपीआई लागू करने के लिए पुल का कोड आवश्यक है C++
ताकि go
इसका उपयोग किया जा सके।
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void* LIB_NewFoo(int value);
void LIB_DestroyFoo(void* foo);
int LIB_FooValue(void* foo);
#ifdef __cplusplus
} // extern "C"
#endif
(4) library-bridge.cpp
पुल के कार्यान्वयन के लिए कोड ।
#include <iostream>
#include "library-bridge.h"
#include "library.hpp"
void* LIB_NewFoo(int value) {
std::cout << "[c++ bridge] LIB_NewFoo(" << value << ")" << std::endl;
auto foo = new Foo(value);
std::cout << "[c++ bridge] LIB_NewFoo(" << value << ") will return pointer "
<< foo << std::endl;
return foo;
}
// Utility function local to the bridge's implementation
Foo* AsFoo(void* foo) { return reinterpret_cast<Foo*>(foo); }
void LIB_DestroyFoo(void* foo) {
std::cout << "[c++ bridge] LIB_DestroyFoo(" << foo << ")" << std::endl;
AsFoo(foo)->~Foo();
}
int LIB_FooValue(void* foo) {
std::cout << "[c++ bridge] LIB_FooValue(" << foo << ")" << std::endl;
return AsFoo(foo)->value();
}
(५) अंत में, library.go
C ++ API पर कॉल करने वाला प्रोग्राम।
package main
// #cgo LDFLAGS: -L. -llibrary
// #include "library-bridge.h"
import "C"
import "unsafe"
import "fmt"
type Foo struct {
ptr unsafe.Pointer
}
func NewFoo(value int) Foo {
var foo Foo
foo.ptr = C.LIB_NewFoo(C.int(value))
return foo
}
func (foo Foo) Free() {
C.LIB_DestroyFoo(foo.ptr)
}
func (foo Foo) value() int {
return int(C.LIB_FooValue(foo.ptr))
}
func main() {
foo := NewFoo(42)
defer foo.Free() // The Go analog to C++'s RAII
fmt.Println("[go]", foo.value())
}
निम्न मेकफाइल का उपयोग करना
liblibrary.so: library.cpp library-bridge.cpp
clang++ -o liblibrary.so library.cpp library-bridge.cpp \
-std=c++17 -O3 -Wall -Wextra -fPIC -shared
मैं उदाहरण कार्यक्रम निम्नानुसार चला सकता हूं:
$ make
clang++ -o liblibrary.so library.cpp library-bridge.cpp \
-std=c++17 -O3 -Wall -Wextra -fPIC -shared
$ go run library.go
[c++ bridge] LIB_NewFoo(42)
[c++] Foo::Foo(42)
[c++ bridge] LIB_NewFoo(42) will return pointer 0x42002e0
[c++ bridge] LIB_FooValue(0x42002e0)
[c++] Foo::value() is 42
[go] 42
[c++ bridge] LIB_DestroyFoo(0x42002e0)
[c++] Foo::~Foo(42)
जरूरी
कार्यक्रम import "C"
में उपरोक्त टिप्पणियां वैकल्पिक नहींgo
हैं । आपको उन्हें बिल्कुल वैसा ही दिखाया जाना चाहिए, ताकि यह पता चले कि इस मामले में कौन से हेडर और लाइब्रेरी को लोड करना है:cgo
// #cgo LDFLAGS: -L. -llibrary
// #include "library-bridge.h"
import "C"
लगता है कि यह गोलंग के बारे में पूछे गए शुरुआती प्रश्नों में से एक है। और उसी समय जवाब कभी अद्यतन नहीं करने के लिए। इन तीन से चार वर्षों के दौरान, कई नए पुस्तकालय और ब्लॉग पोस्ट बाहर हो गए हैं। नीचे कुछ लिंक दिए गए हैं जो मुझे उपयोगी लगे।
C ++ कोड को गो से SWIG के साथ कॉल करना
Gcc गो संकलक, gccgo का उपयोग करते समय C और Go के बीच अंतर के बारे में बात होती है। हालांकि, gccgo का उपयोग करते समय Go की इंटरऑपरेबिलिटी और कार्यान्वित फीचर सेट दोनों की सीमाएं हैं, हालांकि, (उदाहरण के लिए, सीमित गोरोइन, कोई कचरा संग्रह नहीं)।
आप यहाँ अज्ञात क्षेत्र पर चल रहे हैं। सी कोड को कॉल करने के लिए यहां गो उदाहरण दिया गया है, शायद आप ऐसा कुछ कर सकते हैं कि सी ++ नाम के प्रबंध पर पढ़ना और सम्मेलनों को कॉल करना, और बहुत सारे परीक्षण और त्रुटि।
यदि आप अभी भी इसे आज़माने का मन बना रहे हैं, तो शुभकामनाएँ।
यहां समस्या यह है कि एक आज्ञाकारी कार्यान्वयन को अपनी कक्षाओं को एक .cpp फ़ाइल में रखने की आवश्यकता नहीं है। यदि कंपाइलर किसी वर्ग के अस्तित्व को अनुकूलित कर सकता है, तो जब तक कार्यक्रम उसके बिना उसी तरह से व्यवहार करता है, तब तक इसे आउटपुट निष्पादन योग्य से छोड़ा जा सकता है।
C में एक मानकीकृत बाइनरी इंटरफ़ेस है। इसलिए आप यह जान पाएंगे कि आपके कार्य निर्यात किए गए हैं। लेकिन C ++ के पीछे ऐसा कोई मानक नहीं है।
मजेदार यह कि इस घोषणा ने कितने व्यापक मुद्दों को जन्म दिया है। नई भाषाओं को बूटस्ट्रैप करने के तरीके के रूप में इंटरप्रोसेस मानकों को विकसित करने के बारे में डैन लिके ने अपनी वेबसाइट, फ्लटरबाई पर एक बहुत ही मनोरंजक और विचारशील चर्चा की थी (और अन्य व्यवहार है, लेकिन वह एक है जो यहां जर्मे है)।
यह कमांड कोगो का उपयोग करके प्राप्त किया जा सकता है।
संक्षेप में, यदि "C" का आयात तुरंत एक टिप्पणी से पहले होता है, तो उस टिप्पणी को, जिसे प्रस्तावना कहा जाता है, पैकेज के C भागों को संकलित करते समय हेडर के रूप में उपयोग किया जाता है। उदाहरण के लिए: '
स्रोत: https://golang.org/cmd/cgo/
// #include <stdio.h>
// #include <errno.h>
import "C"