import function from .so - c++

I need to import a function from a Linux .so library with boost.dll library. My code is like this:
namespace n1 {
namespace n2 {
struct st {
std::string n;
int m;
}
}
}
void foo(std::string const&, n1::n2::st& attr) {
/*some implementation*/
}
Here I try to import the function foo():
int main(int argc, char** argv) {
boost::filesystem::path path("some path");
boost::dll::experimental::smart_library lib(path);
auto f2 = lib.get_function<void(std::string const&, n1::n2::st&)>(path, "n1::n2::foo"); //<<----here runtime error
f2( std::string(), st{});
}
but I get this runtime error:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl >'
what(): boost::dll::shared_library::get() failed (dlerror system message: /path_to_my_library.so: undefined symbol: n1::n2::foo): Illegal seek

Because n1::n2::foo is not a C-compatible export name, I'd suggest you need either to use the mangled name, or use mangled_import
Caution: This feature is experimental
On my compiler
foo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, n1::n2::st&)
mangles to
_Z3fooRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERN2n12n22stE
On the topic of also importing the struct, see Class Imports
UPDATE
A working sample based on the manual mangling approach:
shared.cpp
#include "shared.h"
#include <iostream>
void foo(std::string const& msg, n1::n2::st& attr) {
std::cout << msg << " from " << __FILE__ << ":" << __LINE__ << " (" << __PRETTY_FUNCTION__ << ")\n";
std::cout << "attr.m = " << attr.m << "\n";
std::cout << "attr.n = " << attr.n << "\n";
}
shared.h
#include <string>
namespace n1 { namespace n2 { struct st { std::string n; int m; }; } }
main.cpp
#include <boost/dll.hpp>
#include <boost/dll/smart_library.hpp>
#include <boost/dll/import_mangled.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <iostream>
#include "shared.h"
int main() {
boost::filesystem::path path("./libshared.so");
try {
boost::dll::experimental::smart_library lib(path);
//auto f1 = boost::dll::experimental::import_mangled<void(std::string const&, n1::n2::st&)>(path, "foo");
auto f1 = boost::dll::import<void(std::string const&, n1::n2::st&)>(path, "_Z3fooRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERN2n12n22stE");
n1::n2::st arg { "world", 42 };
f1("hello", arg);
} catch(boost::exception const& e) {
std::cout << boost::diagnostic_information(e, true) << '\n';
}
}
See it Live On Coliru
Compiled with:
g++ -std=c++14 -shared -fPIC shared.cpp -o libshared.so
g++ -std=c++14 main.cpp -ldl -lboost_system -lboost_filesystem
Show the mangled names with
nm libshared.so
Run the demo with
./a.out
Prints
hello from shared.cpp:5 (void foo(const string&, n1::n2::st&))
attr.m = 42
attr.n = world

Related

In C++ is there a way to call a function with a std::stringstream& argument without the caller using a named variable?

In C++, is it possible to call a function whose argument is std::stringstream& without the caller declaring an explicit named variable of type std::stringstream?
I.e. I would like to accomplish something along the lines of this:
#include <cerrno>
#include <cstring>
#include <iostream>
#include <sstream>
void func(const std::stringstream& ss) {
std::cout << ss.str() << std::endl;
}
int main() {
func("Hello World " << errno << "(" << strerror(errno) << ")");
return 0;
}
The above code generates this compile error:
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
./main.c: In function ‘int main()’:
./main.c:11:23: error: invalid operands of types ‘const char [13]’ and ‘int’ to binary ‘operator<<’
11 | func("Hello World " << errno << "(" << strerror(errno) << ")");
| ~~~~~~~~~~~~~~ ^~
| |
| const char [13]
(I'm not sure if I properly understand the problem -- I think it is because the const char* "Hello World" is not implicitly cast to anything for which the << operator is applicable -- is that correct?)
I tried this next:
#include <cerrno>
#include <cstring>
#include <iostream>
#include <sstream>
void func(const std::stringstream& ss) {
std::cout << ss.str() << std::endl;
}
int main() {
func(std::stringstream("Hello World ") << errno << "(" << strerror(errno) << ")");
return 0;
}
...which had an interesting result: on my PC, with g++ I got the following compile error:
$ g++ -g ./main.c && ./a.out
./main.c: In function ‘int main()’:
./main.c:19:77: error: invalid initialization of reference of type ‘const stringstream&’ {aka ‘const std::__cxx11::basic_stringstream<char>&’} from expression of type ‘std::basic_ostream<char>’
19 | func(std::stringstream("Hello World ") << errno << "(" << strerror(errno) << ")");
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
./main.c:6:36: note: in passing argument 1 of ‘void func(const stringstream&)’
6 | void func(const std::stringstream& ss) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~
If I understand the compile error correctly, the value being passed to func() is of type std::basic_ostream<char> which cannot be implicitly cast to std::stringstream. Is this because the return-value of operator<< is type std::basic_ostream? (https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt)
The interesting part, though, is that at randomly-chosen online C++ compiler https://www.programiz.com/cpp-programming/online-compiler/, the same code compiles, however what gets printed to stdout is:
0(Success)d
...which seems to show the string "Hello World" being overwritten by the the value of errno << "(" << strerror(errno) << ")"
I presume this difference of behavior is due to different compilers, and I would like to understand if/why this is the case -- but this is tangential to the specific question asked here, and I may ask it as a separate, specific question.
tl;dr: in the following code, function main() invokes function func() by using an explicit local, named variable:
#include <cerrno>
#include <cstring>
#include <iostream>
#include <sstream>
void func(const std::stringstream& ss) {
std::cout << ss.str() << std::endl;
}
int main() {
std::stringstream ss;
ss << "Hello World " << errno << "(" << strerror(errno) << ")";
func(ss);
return 0;
}
$ g++ -g ./main.c && ./a.out
Hello World 0(Success)
...is there a way to invoke function func() without the the caller using an explicit, named variable?
Update: I tried the following based on an answer-as-comment:
#include <cerrno>
#include <cstring>
#include <iostream>
#include <sstream>
void func(const std::stringstream& ss) {
std::cout << ss.str() << std::endl;
}
int main() {
func(std::stringstream{} << "Hello World " << errno << "(" << strerror(errno) << ")");
return 0;
}
...which resulted in this compile-error:
$ g++ -g ./main.c && ./a.out
./main.c: In function ‘int main()’:
./main.c:46:81: error: invalid initialization of reference of type ‘const stringstream&’ {aka ‘const std::__cxx11::basic_stringstream<char>&’} from expression of type ‘std::basic_ostream<char>’
46 | func(std::stringstream{} << "Hello World " << errno << "(" << strerror(errno) << ")");
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
./main.c:6:36: note: in passing argument 1 of ‘void func(const stringstream&)’
6 | void func(const std::stringstream& ss) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~
...which looks the same as when I tried func(std::stringstream("Hello World ") << errno << "(" << strerror(errno) << ")");
Update: I tried the following based on an answer-as-comment:
#include <cerrno>
#include <cstring>
#include <iostream>
#include <sstream>
void func(const std::stringstream& ss) {
std::cout << ss.str() << std::endl;
}
int main() {
func((std::stringstream{} << "Hello World " << errno << "(" << strerror(errno) << ")").str());
return 0;
}
...which resulted in this compile error:
$ g++ -g ./main.c && ./a.out
./main.c: In function ‘int main()’:
./main.c:11:90: error: ‘class std::basic_ostream<char>’ has no member named ‘str’
11 | func((std::stringstream{} << "Hello World " << errno << "(" << strerror(errno) << ")").str());
|
One possibility would be to use a string instead of a stringstream:
func(std::string("Hello World ") + std::to_string(errno) + "(" + strerror(errno) + ")");
...or possibly, if you don't mind one extra line elsewhere:
using namespace std::literals;
// ...
func("Hello World "s + std::to_string(errno) + "(" + strerror(errno) + ")");
Either way, you would need to rewrite func to receive an std::string (or a std::string const &) instead of an std::stringstream (but given that all func is doing with it is calling str() to get a string, that doesn't seem like it should be a problem).
Another possibility would be to rewrite func to to be a variadic template:
template <typename... Args>
void func(Args&&... args) {
((std::cout << std::forward<Args>(args)), ...);
// or if you want writing to the stream to be atomic, write them
// to a stringstream then write that to std::cout:
// std::stringstream foo;
// ((foo << std::forward<Args>(args)), ...);
// std::cout << foo.str();
}
int main() {
func("Hello World ", errno, " (", strerror(errno), ")");
}
...which produces the expected result:
Hello World 0 (Success)
May be not what you are looking for, but sometimes it used this way:
#include <cerrno>
#include <cstring>
#include <iostream>
#include <sstream>
namespace { // Just to hide from other modules
class mystream : public std::stringstream
{
public:
~mystream() {
std::cout << str() << std::endl;
}
};
}
mystream func() {
return {};
}
int main() {
func() << "Hello World " << errno << "(" << strerror(errno) << ")";
return 0;
}
As a sidnote, C++ has its own mechanisms to handle errno, you can try to use it this way:
#include <system_error>
#include <iostream>
#include <sstream>
class mystream : public std::stringstream
{
public:
~mystream() {
std::cout << str() << std::endl;
}
};
mystream func() {
return {};
}
int main() {
// Capture error for possible transmission and later processing
std::error_code err{errno, std::system_category()};
// You can compare it to platform-independent enum
if (err == std::errc::invalid_argument)
return 1;
// You can print it
func() << "Hello World " << err.value() << "(" << err.message() << ")";
return 0;
}
You can define a user defined literal.
#include <cstring>
#include <iostream>
#include <sstream>
#include <string>
std::stringstream operator ""_ss(const char* str, size_t size) {
std::stringstream ss;
ss.write(str, size);
return ss;
}
void func(const std::stringstream& ss) {
std::cout << ss.str() << std::endl;
}
int main() {
func("Hello World "_ss << errno << " (" << std::strerror(errno) << ")");
}
// Output:
// Hello World 0 (Success)
https://godbolt.org/z/bn7sq97Wq
As for the compiler error in your second attempt
func((std::stringstream{} << "Hello World " << errno << "(" << strerror(errno) << ")").c_str());
// ^^^^^^^
// Absolutely unnecessary:
func(std::stringstream{} << "Hello World " << errno << "(" << strerror(errno) << ")");
It does not work until GCC 11.2. std::basic_stringstream inherits std::basic_ostream and the returned type of its std::basic_ostream<CharT,Traits>::operator<< is basic_ostream& that is not suitable for const std::stringstream&. The work around is the modified func():
#include <cstring>
#include <iostream>
#include <sstream>
#include <string>
std::stringstream operator ""_ss(const char* str, size_t size) {
std::stringstream ss;
ss.write(str, size);
return ss;
}
void func(const std::ostream& ss) {
std::cout << ss.rdbuf() << std::endl;
}
int main() {
func("Hello World "_ss << errno << " (" << std::strerror(errno) << ")");
}
https://godbolt.org/z/szqvrcbW8

Calling a member function of class using objects giving lookup error

I am trying to build plugins in c++ using boost library. helper.h
Header file:
#include <string>
#ifndef HELPER_H
#define HELPER_H
class Helper
{
public:
std::string s;
void helper_new(std::string a);
};
#endif
I defined the member function in a file helper.cpp
#include "helper.h"
namespace boostfs = boost::filesystem;
namespace boostdll = boost::dll;
namespace dll = boost::dll;
// Member Functions()
void Helper::helper_new(std::string a)
{
//int i=0;
std::cout<<"Inside helper_new function!!";
std::cout<<"\n";
std::cout<<a;
std::cout<<"\n";
/*std::ofstream MyFile("/home/deepansh/Desktop/Plugin_example/outputs/helper.txt");
std::cout << "Writing in helper.txt\n"; */
/*for(i=0;i<LONG_MAX;i++)
for(int j=0;j<LONG_MAX;j++);*/
/*MyFile<<a+" ";
MyFile<<i;
MyFile<<"\n";
MyFile.close();*/
std::cout << "Done\n";
}
int main() {
Helper obj;
std::string a;
std::cout<<"Enter string u want to write?";
std::getline(std::cin, a);
obj.s=a;
int choice=1;
std::cout<<"which strat to use? \'1\' or \'2\' ?(default is 1)";
std::cin>>choice;
std::string file="strat"+std::to_string(choice);
boostfs::path lib_path = boostfs::current_path();
boost::filesystem::path p2(std::string(lib_path.string()).append("/plugins/").append(file).append(".so"));
boost::shared_ptr<plugin_api> plugin; // variable to hold a pointer to plugin variable
std::cout << "Loading the plugin" << std::endl;
plugin = dll::import<plugin_api>( // type of imported symbol is located between `<` and `>`
p2, // path to the library and library name
"plugin", // name of the symbol to import
dll::load_mode::append_decorations // makes `libmy_plugin_sum.so` or `my_plugin_sum.dll` from `my_plugin_sum`
);
plugin->handle_task(obj);
std::cout << plugin->print() << std::endl;
}
I called the member function from another file with the help of object of Helper class passed to it as argument(this is compiles as so file) strat1.cpp
#include "../helper.h"
#include <string>
namespace my_namespace {
class strat : public plugin_api {
public:
strat() {
std::cout << "Constructing start" << std::endl;
}
std::string print() const {
return "Hello from strat 1";
}
int handle_task(Helper a) {
//long i=0;
//std::ofstream fout;
//fout.open("/home/deepansh/Desktop/Plugin_example/outputs/strat1.txt");
std::cout<<"Inside strat 1";
std::cout<<"\n";
/*for(i=0;i<LONG_MAX;i++)
for(int j=0;j<LONG_MAX;j++);*/
//fout<<a.s+" ";
//fout<<i;
//fout<<"\n";
//fout.close();
std::cout<<a.s;
std::cout<<"\n";
std::cout<<"going to the helper class function.";
std::string p="Hello man. What's up?";
a.helper_new(p); //error is here
return 0;
}
~strat() {
std::cout << "Destructing strat ;o)" << std::endl;
}
};
I am getting this error ./a.out: symbol lookup error: /home/deepansh/Desktop/Plugin_example/plugins/strat1.so: undefined symbol: _ZN6Helper10helper_newENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
When compiling the code can someone help. compiling:
Convert the plugin library(plugin implementation) to object file by using:
gcc -c -Wall -Werror -fpic strat1.c ../helper.cpp //here -wall and -Werror are for warnings
Then convert the .o files to .so files using(creating shared library from object file) :
gcc -shared -o strat1.so strat1.o
g++-8 helper.cpp -L/usr/lib/x86_64-linux-gnu -lboost_filesystem -L/usr/lib/x86_64-linux-gnu -lboost_system -ldl
when I run the executable a.out the error occurs

Calling function by its name as string [duplicate]

I wonder if there is a simple way to call a function from a string. I know a simple way, using 'if' and 'else'.
int function_1(int i, int j) {
return i*j;
}
int function_2(int i, int j) {
return i/j;
}
...
...
...
int function_N(int i, int j) {
return i+j;
}
int main(int argc, char* argv[]) {
int i = 4, j = 2;
string function = "function_2";
cout << callFunction(i, j, function) << endl;
return 0;
}
This is the basic approach
int callFunction(int i, int j, string function) {
if(function == "function_1") {
return function_1(i, j);
} else if(function == "function_2") {
return function_2(i, j);
} else if(...) {
} ...
...
...
...
return function_1(i, j);
}
Is there something simpler?
/* New Approach */
int callFunction(int i, int j, string function) {
/* I need something simple */
return function(i, j);
}
What you have described is called reflection and C++ doesn't support it. However you might come with some work-around, for example in this very concrete case you might use an std::map that would map names of functions (std::string objects) to function pointers, which in case of functions with the very same prototype could be easier than it might seem:
#include <iostream>
#include <map>
int add(int i, int j) { return i+j; }
int sub(int i, int j) { return i-j; }
typedef int (*FnPtr)(int, int);
int main() {
// initialization:
std::map<std::string, FnPtr> myMap;
myMap["add"] = add;
myMap["sub"] = sub;
// usage:
std::string s("add");
int res = myMap[s](2,3);
std::cout << res;
}
Note that myMap[s](2,3) retrieves the function pointer mapped to string s and invokes this function, passing 2 and 3 to it, making the output of this example to be 5
Using a map of standard string to standard functions.
#include <functional>
#include <map>
#include <string>
#include <iostream>
int add(int x, int y) {return x+y;}
int sub(int x, int y) {return x-y;}
int main()
{
std::map<std::string, std::function<int(int,int)>> funcMap =
{{ "add", add},
{ "sub", sub}
};
std::cout << funcMap["add"](2,3) << "\n";
std::cout << funcMap["sub"](5,2) << "\n";
}
Even better with Lambda:
#include <functional>
#include <map>
#include <string>
#include <iostream>
int main()
{
std::map<std::string, std::function<int(int,int)>> funcMap =
{{ "add", [](int x, int y){return x+y;}},
{ "sub", [](int x, int y){return x-y;}}
};
std::cout << funcMap["add"](2,3) << "\n";
std::cout << funcMap["sub"](5,2) << "\n";
}
You can also put your functions into a shared library. You will load such library dynamically with dlopen() and then just make the calls to the functions with a std::string. Here an example:
hello.cpp
#include <iostream>
extern "C" void hello() {
std::cout << "hello" << '\n';
}
main.cpp
#include <iostream>
#include <dlfcn.h>
int main() {
using std::cout;
using std::cerr;
cout << "C++ dlopen demo\n\n";
// open the library
cout << "Opening hello.so...\n";
void* handle = dlopen("./hello.so", RTLD_LAZY);
if (!handle) {
cerr << "Cannot open library: " << dlerror() << '\n';
return 1;
}
// load the symbol
cout << "Loading symbol hello...\n";
typedef void (*hello_t)();
// reset errors
dlerror();
std::string yourfunc("hello"); // Here is your function
hello_t hello = (hello_t) dlsym(handle, yourfunc.c_str());
const char *dlsym_error = dlerror();
if (dlsym_error) {
cerr << "Cannot load symbol 'hello': " << dlsym_error <<
'\n';
dlclose(handle);
return 1;
}
// use it to do the calculation
cout << "Calling hello...\n";
hello();
// close the library
cout << "Closing library...\n";
dlclose(handle);
}
compilation:
g++ -fPIC -shared hello.cpp -o hello.so
and:
g++ main.cpp -o main -ldl
run:
C++ dlopen demo
Opening hello.so...
Loading symbol hello...
Calling hello...
hello
Closing library...
The example was stolen from here. There you can find more detailed explanation on dlopen() and c++
There is another possibility which hasn't been mentioned yet, which is true reflection.
An option for this is accessing functions exported from an executable or a shared library using operating system functions for resolving names to addresses. This has interesting uses like loading two 'contestant' dlls into an 'umpire' program, so that people can slug it out by having their actual codes fight each other (playing Reversi or Quake, whatever).
Another option is accessing the debug information created by the compiler. Under Windows this can be surprisingly easy for compilers that are compatible, since all the work can be off-loaded to system dlls or free dlls downloadable from Microsoft. Part of the functionality is already contained in the Windows API.
However, that falls more into the category of Systems Programming - regardless of language - and thus it pertains to C++ only insofar as it is the Systems Programming language par excellence.

How do I use STL algorithms with ICU's iterators?

I wonder how to use ICU library iterators with STL. For instance, what if we decided to output all permutations of a string?
With std::string it looks like the following:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
static void _usage(const char *executable)
{
cout << "Usage: " << executable << " <string>" << endl;
}
int main (int argc, char const* argv[]) {
if (argc < 2) {
cerr << "Target string expected" << endl;
_usage(argv[0]);
return 1;
}
string s(argv[1]);
do {
cout << s << endl;
} while (next_permutation(s.begin(), s.end()));
return 0;
}
I tried to do the same using ICU:
#include <unicode/unistr.h>
#include <unicode/uchriter.h>
#include <unicode/ustdio.h>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
static void _usage(const char *executable)
{
cout << "Usage: " << executable << " <string>" << endl;
}
int main (int argc, char const* argv[]) {
if (argc < 2) {
cerr << "Target string expected" << endl;
_usage(argv[0]);
return 1;
}
UnicodeString ustr(argv[1]);
UChar *uc = ustr.getBuffer(-1);
int32_t len = u_strlen(uc);
UCharCharacterIterator iter_start(uc, len);
UCharCharacterIterator iter_end(uc, len, len - 1);
do {
// XXX
} while (next_permutation(iter_start, iter_end ));
return 0;
}
But it fails to compile:
x86_64-pc-linux-gnu-g++ -I/usr/include -licuio -licui18n -licuuc -licudata permute2.C -o permute2
In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/algorithm:63:0,
from permute2.C:4:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h: In function ‘bool std::next_permutation(_BIter, _BIter) [with _BIter = icu_49::
UCharCharacterIterator]’:
permute2.C:31:49: instantiated from here
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3531:7: error: no match for ‘operator++’ in ‘++__i’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3535:7: error: no match for ‘operator--’ in ‘--__i’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3540:4: error: no match for ‘operator--’ in ‘--__i’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3541:4: error: no match for ‘operator*’ in ‘*__ii’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3541:4: error: no match for ‘operator*’ in ‘*__i’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3544:8: error: no match for ‘operator--’ in ‘--__j’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.4/include/g++-v4/bits/stl_algo.h:3544:8: error: no match for ‘operator*’ in ‘*__i’
...
What's the proper way to make use of STL with ICU? Extend the UCharCharacterIterator class and provide code for all these operators?

Boost coroutine assertion failure

To try out the new coroutine feature in boost I created the following program:
#include <boost/coroutine/all.hpp>
#include <string>
#include <vector>
typedef boost::coroutines::coroutine<int(char)> coroutine_t;
void f(coroutine_t::caller_type & ca)
{
std::vector<int> vec = {1, 2, 3};
for (int i : vec)
{
char c = ca.get();
std::cout << "c: " << c << std::endl;
ca(i);
}
}
int main()
{
coroutine_t cr(f);
std::string str("abc");
for (char c : str)
{
std::cout << c << std::flush;
cr(c);
int n = cr.get();
std::cout << n << std::endl;
}
}
The code is based on the sample code from the docs.
My build command goes as follows:
$ g++ -std=c++11 -o test -I/usr/local/include -L/usr/local/lib main.cpp /usr/local/lib/libboost_context.a
Output:
$ ./test
test: /usr/local/include/boost/coroutine/detail/coroutine_get.hpp:43: typename boost::coroutines::detail::param<Result>::type boost::coroutines::detail::coroutine_get<D, Result, arity>::get() const [with D = boost::coroutines::coroutine<char(int), 1>; Result = char; int arity = 1; typename boost::coroutines::detail::param<Result>::type = char]: Assertion `static_cast< D const* >( this)->impl_->result_' failed.
Aborted (core dumped)
The program is aborted due to failed assertion. Can you help me find the error in my code?
I believe you need to add a call ca() at the beginning of your function f.
From the boost documentation:
The execution control is transferred to coroutine at construction (coroutine-function entered) - when control should be returned to the original calling routine, invoke boost::coroutines::coroutine<>::operator() on the first argument of type boost::coroutines::coroutine<>::caller_type inside coroutine-function.