নতুন গো ভাষায় আমি সি ++ কোডটি কীভাবে কল করব? অন্য কথায়, আমি কীভাবে আমার সি ++ ক্লাসগুলি গুটিয়ে রাখতে পারি এবং সেগুলিকে গো-এ ব্যবহার করতে পারি?
নতুন গো ভাষায় আমি সি ++ কোডটি কীভাবে কল করব? অন্য কথায়, আমি কীভাবে আমার সি ++ ক্লাসগুলি গুটিয়ে রাখতে পারি এবং সেগুলিকে গো-এ ব্যবহার করতে পারি?
উত্তর:
আপডেট: আমি একটি ছোট পরীক্ষার সি ++ শ্রেণিকে গোয়ের সাথে সংযুক্ত করতে সফল হয়েছি
আপনি যদি একটি সি ইন্টারফেসের সাথে আপনার সি ++ কোডটি আবদ্ধ করেন তবে আপনাকে আপনার লাইব্রেরিটি সিজিও দিয়ে কল করতে সক্ষম হতে হবে (জিএমপি-এর উদাহরণ দেখুন $GOROOT/misc/cgo/gmp
)।
আমি নিশ্চিত নই যে সি ++ তে কোনও শ্রেণীর ধারণা গোয়ে সত্যই প্রকাশযোগ্য, কারণ এর উত্তরাধিকার নেই।
এখানে একটি উদাহরণ:
আমার একটি সি ++ শ্রেণি সংজ্ঞায়িত হয়েছে:
// 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
ছাড়াই কাজ করা উচিত
দেখে মনে হচ্ছে যে বর্তমানে এসডব্লিউআইজি এর পক্ষে সেরা সমাধান:
http://www.swig.org/Doc2.0/Go.html
এটি উত্তরাধিকারকে সমর্থন করে এবং এমনকি গো স্ট্রাক্টের সাথে সি ++ শ্রেণিকে সাবক্লাস করার অনুমতি দেয় তাই যখন সি ++ কোডে ওভাররাইড পদ্ধতিগুলি বলা হয়, গো কোডটি বরখাস্ত করা হয়।
গো এফএকিউ-তে সি ++ সম্পর্কিত বিভাগ আপডেট করা হয়েছে এবং এখন এসডিজিআইজি-র উল্লেখ রয়েছে এবং " কারণ গো ময়লা-আবর্জনা সংগ্রহ করা এটি বুদ্ধিমানের কাজ হবে না, কমপক্ষে নির্লজ্জভাবে "।
আমি প্রায়শই জিজ্ঞাসিত প্রশ্নে যা পড়েছি তা থেকে আপনি এখনও পুরোপুরি পারবেন না :
গো প্রোগ্রামগুলি সি / সি ++ প্রোগ্রামগুলির সাথে লিঙ্ক করে?
দুটি গো সংকলক বাস্তবায়ন রয়েছে, গিসি (g জি প্রোগ্রাম এবং বন্ধু) এবং জিসিসিগো। জিসি একটি ভিন্ন কলিং কনভেনশন এবং লিঙ্কার ব্যবহার করে এবং তাই একই সম্মেলনটি ব্যবহার করে কেবল সি প্রোগ্রামগুলির সাথেই লিঙ্ক করা যেতে পারে। এমন সি সংকলক রয়েছে তবে কোনও সি ++ সংকলক নেই। জিসিসিগো একটি জিসিসি ফ্রন্ট-এন্ড যা যত্ন সহ, জিসিসি-সংকলিত সি বা সি ++ প্রোগ্রামগুলির সাথে যুক্ত হতে পারে।
কো কোড থেকে সি লাইব্রেরিগুলিকে নিরাপদে কল করার অনুমতি দেওয়ার জন্য কোগো প্রোগ্রামটি "বিদেশী ফাংশন ইন্টারফেস" এর প্রক্রিয়া সরবরাহ করে। এসডাব্লুআইজি এই ক্ষমতাটি সি ++ লাইব্রেরিতে প্রসারিত করে।
Go1.2 + হিসাবে, cgo স্বয়ংক্রিয়ভাবে সি ++ কোড অন্তর্ভুক্ত করে এবং সংকলন করে:
আমি স্কট ওয়েলসের উত্তরের ভিত্তিতে নিম্নলিখিত উদাহরণটি তৈরি করেছি । আমি এটি ম্যাকোস হাই সিয়েরা 10.13.3 চলমান go
সংস্করণে পরীক্ষা করেছি go1.10 darwin/amd64
।
(1) এর জন্য কোড library.hpp
, C ++ API কল করার লক্ষ্য আমাদের aim
#pragma once
class Foo {
public:
Foo(int value);
~Foo();
int value() const;
private:
int m_value;
};
(২) এর জন্য কোড library.cpp
, সি ++ বাস্তবায়ন।
#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
(৪) library-bridge.cpp
সেতুটি কার্যকর করার জন্য কোড Code
#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();
}
(5) পরিশেষে, library.go
গো প্রোগ্রামটি C ++ এপিআই কল করে।
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())
}
নিম্নলিখিত Makefile ব্যবহার করে
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"
মনে হচ্ছে এটি গোলাং সম্পর্কে প্রাথমিক জিজ্ঞাসিত একটি প্রশ্ন। এবং একই সাথে উত্তরগুলি কখনই আপডেট হয় না। এই তিন থেকে চার বছরের মধ্যে, অনেকগুলি নতুন গ্রন্থাগার এবং ব্লগ পোস্ট বেরিয়েছে। নীচের কয়েকটি লিঙ্ক যা আমি দরকারী বলে মনে করি।
সি ++ কোড থেকে ফায়ার এস এস এস আই জি জি-র কল করা হচ্ছে
সেখানে কথা হলো সি এবং যান মধ্যে উৎপন্ন যখন জিসিসি যান কম্পাইলার ব্যবহার করে, gccgo। আন্তঃব্যবহারযোগ্যতা এবং জিসিসিগো ব্যবহার করার সময় গো এর প্রয়োগকৃত বৈশিষ্ট্য সেট উভয়ই সীমাবদ্ধতা রয়েছে (যেমন, সীমিত গোরোটাইনস, কোনও আবর্জনা সংগ্রহ নয়)।
আপনি এখানে নিরক্ষিত অঞ্চলে হাঁটছেন। সি কোড কল করার জন্য এখানে গো উদাহরণ দেওয়া আছে, সম্ভবত আপনি সি ++ নাম ম্যাংলিং এবং কলিং কনভেনশনগুলি পড়ার পরে এবং প্রচুর পরীক্ষা এবং ত্রুটির পরে এমন কিছু করতে পারেন ।
আপনি যদি এখনও চেষ্টা করে দেখতে চান তবে শুভকামনা রইল।
এখানে সমস্যাটি হল যে একটি কমপ্লায়েন্ট বাস্তবায়নের জন্য আপনার ক্লাসগুলি একটি সংকলন .cpp ফাইলে রাখার দরকার নেই। যদি সংকলক কোনও শ্রেণীর অস্তিত্বকে অনুকূল করে তুলতে পারে, যতক্ষণ না প্রোগ্রামটি একইভাবে আচরণ করে, তবে এটি নির্বাহযোগ্যকে আউটপুট থেকে বাদ দেওয়া যেতে পারে।
সি এর একটি মানক বাইনারি ইন্টারফেস রয়েছে। সুতরাং আপনি জানতে পারবেন যে আপনার ফাংশনগুলি রফতানি হয়েছে। তবে এর পিছনে সি ++ এর কোনও মান নেই has
এই ঘোষণাটি কীভাবে বিস্তৃত হয়েছে তা মজার বিষয়। ড্যান লাইক তার ওয়েবসাইট ফ্লুটারবিতে নতুন ভাষার বুটস্ট্র্যাপিংয়ের পদ্ধতি হিসাবে (এবং অন্যান্য পদক্ষেপগুলি, তবে এটিই জার্মানী is) এটির জন্য ইন্টারপ্রসেস স্ট্যান্ডার্ডগুলি বিকাশের বিষয়ে একটি খুব বিনোদনমূলক এবং চিন্তাশীল আলোচনা করেছিলেন ।
কমান্ড cgo ব্যবহার করে এটি অর্জন করা যেতে পারে।
সংক্ষেপে 'যদি "সি" এর আমদানি একটি মন্তব্যের সাথে সাথেই আগে ঘটে থাকে, প্যাকেজটির সি অংশগুলি সংকলন করার সময় এই মন্তব্যটিকে, উপস্থাপনা নামে অভিহিত করা হয় a উদাহরণস্বরূপ: '
উত্স: https://golang.org/cmd/cgo/
// #include <stdio.h>
// #include <errno.h>
import "C"