I don't understand why RubyInline is crashing.
class CPPCode
inline do |builder|
builder.include '<algorithm>'
builder.include '<vector>'
builder.c 'int test(){return 1;}'
end
end
The error:
error executing "gcc -shared -fPIC -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration -Wdeprecated-declarations -Wno-packed-bitfield-compat -fPIC -L. -fstack-protector -rdynamic -Wl,-export-dynamic -I /home/lionzxy/.rvm/rubies/ruby-2.3.0/include/ruby-2.3.0 -I /home/lionzxy/.rvm/rubies/ruby-2.3.0/include/ruby-2.3.0/x86_64-linux -I /home/lionzxy/.rvm/rubies/ruby-2.3.0/include -L/home/lionzxy/.rvm/rubies/ruby-2.3.0/lib -o \"/home/lionzxy/.ruby_inline/ruby-2.3.0/Inline_Book__CPPCode_232b56c4fe2ef7959c8f3c1f6db3cebb.so\" \"/home/lionzxy/.ruby_inline/ruby-2.3.0/Inline_Book__CPPCode_232b56c4fe2ef7959c8f3c1f6db3cebb.c\" ": pid 24454 exit 1 Renamed /home/lionzxy/.ruby_inline/ruby-2.3.0/Inline_Book__CPPCode_232b56c4fe2ef7959c8f3c1f6db3cebb.c to /home/lionzxy/.ruby_inline/ruby-2.3.0/Inline_Book__CPPCode_232b56c4fe2ef7959c8f3c1f6db3cebb.c.bad
Generated C++ file:
#include "ruby.h"
#include <algorithm>
#include <vector>
# line 58 "/home/lionzxy/RubymineProjects/app/models/book.rb"
static VALUE test(VALUE self) {
return INT2FIX(1);}
#ifdef __cplusplus
extern "C" {
#endif
void Init_Inline_Book__CPPCode_098f6bcd4621d373cade4e832627b4f6() {
VALUE c = rb_cObject;
c = rb_const_get(c, rb_intern("Book"));
c = rb_const_get(c, rb_intern("CPPCode"));
rb_define_method(c, "test", (VALUE(*)(ANYARGS))test, 0);
}
#ifdef __cplusplus
}
#endif
You're trying to use C++ code, but you're running gcc without any flags to tell it that it's C++ code.
On the first documentation page we see an example on how to use C++ code:
require 'inline'
class MyTest
inline(:C) do |builder|
builder.include '<iostream>'
builder.add_compile_flags '-x c++', '-lstdc++'
builder.c '
void hello(int i) {
while (i-- > 0) {
std::cout << "hello" << std::endl;
}
}'
end
end
t = MyTest.new()
t.hello(3)
The "trick" here is:
builder.add_compile_flags '-x c++', '-lstdc++'
which tells gcc that this is C++ code.
Related
I have overloaded new globally in get_seven.cpp. Also, I am using -fvisibility=hidden option, but still If I do new from get_seven.cpp, my new is called. I do not want that. How can I achieve that provided
I don't want to use statically linked libstdc++
Keep overload global only
Is there a way that I can make visibility hidden work through code or some compiler flags.
Command to run: ./demonstrate.sh
demonstrate.sh
#!/usr/bin/env sh
echo "Without -fvisibility=hidden:"
make clean && make && ./test
echo
echo "With -fvisibility=hidden:"
make clean && SO_CFLAGS=-fvisibility=hidden make && ./test
#make clean && make && ./test
// get_seven.h
// Returns 7 from PublicGetSeven
#include <cstddef>
//#ifdef __cplusplus
//extern "C" {
//#endif
__attribute__((__visibility__("default"))) int PublicGetSeven();
//__attribute__((__visibility__("hidden"))) void* operator new(size_t nSize);
//#ifdef __cplusplus
//}
//#endif
get_seven.cpp
#include "get_seven.h"
#include <iostream>
#include "malloc.h"
#pragma GCC visibility push(hidden)
int internal_do_calculation();
#pragma GCC visibility pop
#pragma GCC visibility push(hidden)
__attribute__((__visibility__("hidden"))) void* operator new(size_t nSize) {
std::cout << "my new called" << std::endl;
return malloc(nSize);
}
void operator delete(void* pMem) {
std::cout << "my delete called" << std::endl;
free(pMem);
}
#pragma GCC visibility pop
#pragma GCC visibility push(default)
int PublicGetSeven() {
return internal_do_calculation();
}
int internal_do_calculation() {
int* n = new int;
return 7;
}
#pragma GCC visibility pop
get_three.h
// get_three.h
// Returns 3 from PublicGetThree
#ifdef __cplusplus
extern "C" {
#endif
__attribute__((__visibility__("default"))) int PublicGetThree();
#ifdef __cplusplus
}
#endif
get_three.cpp
#include "get_three.h"
#pragma GCC visibility push(hidden)
int internal_do_calculation();
int PublicGetThree() {
return internal_do_calculation();
}
int internal_do_calculation() {
int* n = new int;
return 3;
}
#pragma GCC visibility pop
Makefile
CFLAGS+=-g -Wall
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
FINAL_EXE_LDFLAGS+=-Wl,-rpath=.
endif
ALL: test
test: test.cpp libget_three.so libget_seven.so
g++ -g $(CFLAGS) $(FINAL_EXE_LDFLAGS) -lstdc++ -o test test.cpp -L. -lget_three -lget_seven -Wl,-Bsymbolic
#g++ -g $(CFLAGS) $(FINAL_EXE_LDFLAGS) -lstdc++ -o test test.cpp -L. -lget_three -lget_seven -Wl,-Bsymbolic -static-libstdc++
#g++ $(CFLAGS) $(FINAL_EXE_LDFLAGS) -o test test.cpp -L. -lget_three -lget_seven #-L./glibc-2.27/bld/ -lc #-lc
#g++ $(CFLAGS) $(FINAL_EXE_LDFLAGS) -o test test.cpp -L. -lget_three -lget_seven #-L./glibc-2.36/bld libc.a #-lc
libget_three.so: get_three.o
g++ -o libget_three.so -shared get_three.o -g -Wl,-Bsymbolic
#g++ -o libget_three.so -shared get_three.o -g -Wl,-Bsymbolic -static-libstdc++
get_three.o: get_three.cpp get_three.h
g++ $(CFLAGS) $(SO_CFLAGS) -o get_three.o -c -fPIC get_three.cpp -g -Wl,-Bsymbolic
#g++ $(CFLAGS) $(SO_CFLAGS) -o get_three.o -c -fPIC get_three.cpp -g -Wl,-Bsymbolic -static-libstdc++
libget_seven.so: get_seven.o
g++ -o libget_seven.so -shared get_seven.o -g -Wl,-Bsymbolic
#g++ -o libget_seven.so -shared get_seven.o -g -Wl,-Bsymbolic -static-libstdc++
get_seven.o: get_seven.cpp get_seven.h
g++ $(CFLAGS) $(SO_CFLAGS) -o get_seven.o -c -fPIC get_seven.cpp -g -Wl,-Bsymbolic
#g++ $(CFLAGS) $(SO_CFLAGS) -o get_seven.o -c -fPIC get_seven.cpp -g -Wl,-Bsymbolic -static-libstdc++
clean:
rm -f test libget_three.so libget_seven.so *.o
test.cpp
#include <stdio.h>
#include "get_three.h"
#include "get_seven.h"
int main() {
printf("PublicGetThree returned %d\n", PublicGetThree());
printf("PublicGetSeven returned %d\n", PublicGetSeven());
}
For this struct and function:
typedef struct data_s
{
int i1;
int i2;
} data_t;
void print_data_passed_by_ptr(const data_t *data)
{
printf(" i1 = %i\n"
" i2 = %i\n\n",
data->i1,
data->i2);
}
this works fine in C:
// Print R-value struct passed by ptr
print_data_passed_by_ptr(&(data_t){
.i1 = 7,
.i2 = 8,
});
My C build command is:
gcc -Wall -Wextra -Werror -O3 -std=c17 \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
But, in C++ it fails with
error: taking address of temporary [-fpermissive]
My C++ build command is:
g++ -Wall -Wextra -Werror -O3 -std=c++17 \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
So, I added -fpermissive to my C++ build command:
g++ -Wall -Wextra -Werror -O3 -std=c++17 -fpermissive \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
and now the C++ build fails with this:
error: taking address of temporary [-Werror=permissive]
I tried turning off -Werror=permissive with -Wno-error=permissive (see here for that GCC documentation: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html, and search the page for -Wno-error=), but that's not a valid option. New build cmd I attempted:
g++ -Wall -Wextra -Werror -O3 -std=c++17 -fpermissive -Wno-error=permissive \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
...fails with:
cc1plus: error: -Werror=permissive: no option -Wpermissive
So, how do I solve this to force this C code to build in C++? Either suppressing the warning/error, OR providing some modification to the code other than the one shown just below are acceptable answers. I want the code to compile as C also, not just C++, in the end.
I know I can use "const reference" in C++ instead of ptr, like this, and that's great and all and it might answer somebody else's question, but that's not my question:
void print_data_passed_by_cpp_reference(const data_t& data)
{
printf(" i1 = %i\n"
" i2 = %i\n\n",
data.i1,
data.i2);
}
// Print R-value struct passed by C++ reference
print_data_passed_by_cpp_reference({
.i1 = 9,
.i2 = 10,
});
I also know I can remove -Werror and keep -fpermissive to make it build, with warnings, like this:
eRCaGuy_hello_world/cpp$ g++ -Wall -Wextra -O3 -std=c++17 -fpermissive \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
struct_pass_R_values_by_cpp_reference_and_ptr.c: In function ‘int main()’:
struct_pass_R_values_by_cpp_reference_and_ptr.c:87:5: warning: taking address of temporary [-fpermissive]
});
^
Hello world.
i1 = 7
i2 = 8
i1 = 9
i2 = 10
...but I'd really like to keep -Werror on and make that warning go away.
How to automatically pass an R-value parameter into a function as a const ptr for C and as a const reference for C++
(emphasis added to my original quote)
So, how do I solve this to force this C code to build in C++? Either suppressing the warning/error, OR providing some modification to the code other than the one shown just below are acceptable answers. I want the code to compile as C also, not just C++, in the end.
This works! It is one approach. If there are ways to disable the warning/error in gcc via command-line options I'd still like to know those though.
This is pretty clever I think. It passes the R-value by const ptr for C and by const reference for C++ by using two separate definitions for the print_data() function and the DATA_T macro, depending on the language.
#ifndef __cplusplus
// For C
void print_data(const data_t *data)
{
printf(" i1 = %i\n"
" i2 = %i\n\n",
data->i1,
data->i2);
}
#else
// For C++
void print_data(const data_t& data)
{
printf(" i1 = %i\n"
" i2 = %i\n\n",
data.i1,
data.i2);
}
#endif
#ifndef __cplusplus
// For C
#define DATA_T &(data_t)
#else
// For C++
#define DATA_T // leave empty
#endif
Usage:
// Print R-value struct passed by C++ reference, OR by C ptr, depending on
// whether this code is compiled as C or C++
print_data(DATA_T{
.i1 = 9,
.i2 = 10,
});
Build commands:
# For C
gcc -Wall -Wextra -Werror -O3 -std=c17 \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
# For C++
g++ -Wall -Wextra -Werror -O3 -std=c++17 \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
I am using the Intel Pin tool to generate a shared object file from a C source file and a C++ pintool. I have used the following g++ commands to generate my shared object file. Apologies in advance as the commands are very big due to the Pin libraries and options.
g++ -DBIGARRAY_MULTIPLIER=1 -Wall -Werror -Wno-unknown-pragmas -D__PIN__=1 -DPIN_CRT=1 -fno-stack-protector -fno-exceptions -funwind-tables -fasynchronous-unwind-tables -fno-rtti -DTARGET_IA32E -DHOST_IA32E -fPIC -DTARGET_LINUX -fabi-version=2 -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/include/pin -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/include/pin/gen -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/stlport/include -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/libstdc++/include -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include/arch-x86_64 -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include/kernel/uapi -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include/kernel/uapi/asm-x86 -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/components/include -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/xed-intel64/include/xed -Iinc -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/tools/InstLib -O0 -c -o obj-intel64/testcpp.o testcpp.cpp
g++ -DBIGARRAY_MULTIPLIER=1 -Wall -Werror -Wno-unknown-pragmas -D__PIN__=1 -DPIN_CRT=1 -fno-stack-protector -fno-exceptions -funwind-tables -fasynchronous-unwind-tables -fno-rtti -DTARGET_IA32E -DHOST_IA32E -fPIC -DTARGET_LINUX -fabi-version=2 -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/include/pin -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/include/pin/gen -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/stlport/include -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/libstdc++/include -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include/arch-x86_64 -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include/kernel/uapi -isystem /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/crt/include/kernel/uapi/asm-x86 -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/components/include -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/xed-intel64/include/xed -Iinc -I/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/tools/InstLib -O0 -c -o obj-intel64/test.o test.c
g++ -shared -Wl,-z,defs -Wl,--hash-style=sysv /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/intel64/runtime/pincrt/crtbeginS.o -Wl,-Bsymbolic -Wl,--version-script=/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/source/include/pin/pintool.ver -fabi-version=2 obj-intel64/testcpp.so -o obj-intel64/testcpp.o obj-intel64/test.o -L/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/intel64/runtime/pincrt -L/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/intel64/lib -L/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/intel64/lib-ext -L/home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/extras/xed-intel64/lib -lpin -lxed /home/rohit/github_repos/uli/src/pin/pin-3.2-81205-gcc-linux/intel64/runtime/pincrt/crtendS.o -lpin3dwarf -ldl-dynamic -nostdlib -lstlport-dynamic -lm-dynamic -lc-dynamic -lunwind-dynamic
testcpp.cpp is my C++ pintool and test.c is my C source file. The folder inc contains the header file test.h which is included in both of them.
This is my C++ file -
#include "pin.H"
#include <iostream>
#include <fstream>
extern "C" {
#include <test.h>
}
using namespace std;
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "test.out","This pin tool simulates ULI");
FILE * op;
VOID Instruction(INS ins, void *v) {
}
VOID Fini(INT32 code, VOID *v) {
fprintf(op,"Ended from c++\n");
fprintf(op,"%d\n",cfunc(11,2));
fclose(op);
}
INT32 Usage() {
PIN_ERROR("This Pintool failed\n" + KNOB_BASE::StringKnobSummary() + "\n");
return -1;
}
int main(int argc, char *argv[]) {
if (PIN_Init(argc, argv))
return Usage();
op = fopen("test.out", "w");
PIN_InitSymbols();
INS_AddInstrumentFunction(Instruction, 0);
PIN_AddFiniFunction(Fini, 0);
PIN_StartProgram();
return 0;
}
This is my C file-
#include <stdio.h>
#include <test.h>
int cfunc(int a, int b)
{
return(a+b);
}
void cfunc2()
{
printf("Hello from C %d\n",cfunc(3,5));
}
This is my test.h file-
int cfunc(int, int);
void cfunc2(void);
The rest of the options are pin specific and I simply used them from the sample programs and feel that they don't need modifications (I hope so!)
However when I generate my shared object file I get this error-
obj-intel64/testcpp.o: In function `Fini(int, void*)':
testcpp.cpp:(.text+0x41): undefined reference to `cfunc2'
collect2: error: ld returned 1 exit status
cfunc2 is the function I am trying to call. I do not understand where I am going wrong. I am including the right options and arguments, but somehow this symbol is undefined. Any suggestions?
You use g++ to compile the test.c file. The g++ compiler driver invokes the C++ compiler for .c files, so your functions will have C++ linkage, not C linkage. There are several ways to address thos:
Compile test.c with gcc instead of g++.
Drop the extern "C" from the C++ source file, so that C++ linkage is used everywhere.
Put the extern "C" into the header file, so that applies to the definition in test.c, too.
I have the following code...
// My.h
#include <string>
....
// My.cpp
#include "My.h"
...
errMsg = "X value [too low]: " + std::to_string(xInVal);
But when I compile like...
//setup.py
extra_compile_args =['-std=c++11']
//console output
gcc -Wno-unused-result -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -ggdb -O2 -pipe -Wimplicit-function-declaration -fdebug-prefix-map=/usr/src/ports/python3/python3-3.4.3-1.x86_64/build=/usr/src/debug/python3-3.4.3-1 -fdebug-prefix-map=/usr/src/ports/python3/python3-3.4.3-1.x86_64/src/Python-3.4.3=/usr/src/debug/python3-3.4.3-1 -I./My -c ./My.cpp -o build/temp.cygwin-2.2.1-x86_64-3.4/./My.o -std=c++11
I get the following error....
error: ‘to_string’ is not a member of ‘std’
errMsg = "X value [too low]: " + std::to_string(xInVal);
What am I missing how do I use to_string in this way?
From the CYGWIN headers, it looks like for C++11 these are not defined unless _GLIBCXX_USE_C99 is defined They are enclosed in this if:
#if __cplusplus >= 201103L && defined(_GLIBCXX_USE_C99)
I tried defining _GLIBCXX_USE_C99 but that didn't work for my project. You can try defining it before you use the string header.
I recently had a similar issue with C++11 on CYGWIN related to __STRICT_ANSI__
example.h:
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Math {
public:
int pi() const;
void pi(int pi);
private:
int _pi;
};
#endif
example.cpp:
#include "example.h"
int Math::pi() const {
return this->_pi;
}
void Math::pi(int pi) {
this->_pi = pi;
}
example.swig:
%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}
%include "example.h"
I then generate the wrappers, "example.py" and "example_wrap.c" using:
swig -python example.swig
When I try to compile the wrapper class using:
g++ -fPIC -c example.cpp example_wrap.c -I/usr/local/include/python2.6/
I get the following error:
example_wrap.cpp: In function "PyObject* Swig_var_Math_get()":
example_wrap.cpp:2725: error: expected primary-expression before "void"
example_wrap.cpp:2725: error: expected ")" before "void"
The Error is at the following line :
pyobj = SWIG_NewPointerObj(SWIG_as_voidptr(&Math), SWIGTYPE_p_class, 0 );
#define SWIG_as_voidptr(a) (void *)((const void *)(a))
Is it the right way to generate the wrapper class "example_wrap.c"?
I think the swig command should be "swig -c++ -python example.swig"
There's not enough information here to be sure what's wrong, but I have two ideas for things you can try.
Your g++ invocation is compiling a C source file as if it were C++. This is not guaranteed to work. Try instead
gcc -I/usr/local/include/python2.6 -fPIC -c example_wrap.c
gcc -I/usr/local/include/python2.6 -fPIC -c example.cpp
g++ -shared example_wrap.o example.o -o example.so
(yes, srsly, only use g++ for the link)
If that doesn't work, compile example_wrap.c like this:
gcc -I/usr/local/include/python2.6 -fPIC -c -save-temps example_wrap.c
That will fail the same way but will produce a file named example_wrap.i which is the result of preprocesing. It will be gigantic. Search that file for the function Swig_var_Math_get, and add to your question the complete text of that function (but nothing else).
Thanks for your replay!
The -C++ option generated the C++ class for the wrapper.
swig -c++ -v -python example.swig
I used g++ to compile the wrapper.
g++ -fPIC -c example.cpp example_wrap.cxx -I/usr/local/include/python2.6/
And the following command to buikd the shared object. Ofcourse, we need to remove the superflous includes (-I) and libraries (-L). The important flags are '-shared' and '-fPIC'.
g++ example_wrap.o example.o -L/u01/app/oracle/product/1020.full/lib -I/usr/local/ssl/include -L/usr/local/ssl/lib -lclntsh -lssl -lcrypto -ldl -L/usr/local/lib -L/lib64 -L/usr/local/lib/python2.6/ -lboost_system -lboost_filesystem -lboost_thread -lboost_date_time -lglog -lmodpbase64 -lpthread -ldl -lrt -shared -fPIC -o _example.so