How to wrap a C++ function? - c++

I'm trying to wrap a c++ function called i_receive() by following this tutorial, I first created a wrap.c file, the content of this file is like this:
int i_receive(const uint32_t *f, int32_t t){
static int (*real_i_receive)(const uint32_t *, int32_t)=NULL;
printf("hello world");
return real_i_receive;
}
I compiled this file with gcc -fPIC -shared -o wrap.so wrap.c -ldl, when I used the LD_PRELOAD to run some C++ code with LD_PRELOAD=/full/path/to/wrap.so ./mycppcode I got this message:
ERROR: ld.so: object '/full/path/to/wrap.so' from LD_PRELOAD cannot be preloaded: ignored`.
I was guessing the reason might be that the wrap file is a C file, and I'm using it with C++ code, am I right?
I changed the file to wrap.cc with the same content, when compiling in the same way as before, I got:
ERROR: invalid conversion from 'int (*)(const uint32_t*, int32_t)' to 'int'

First of all, your 2nd error your are getting becase you are returning a Pointer to function type instead of a int type.
If you want to return an int, call the function from the code :
return real_i_receive(f,t);
Notice the "()" which means a function call.
Regarding your guess : it doesn't matter if you are using C or C++ code, the libaries are all assembly code.
One difference between exporting C functions and C++ functions is the name mangling. You would rather export a function as a C function to be able to access it inside your library through unmagled name.
To export a function without name mangling it, you can use extern "C" .

Replace
return real_i_receive;
with
return real_i_receive(f, t);
As it is, the return type of your function is int but you're returning a function pointer.

Related

How to run a Fortran program within GNU Octave?

I want to run a Fortran program within Octave. I would like to do this for automation purposes and use Octave for all the data processing.
Is it possible to run a Fortran program from octave using cygwin, if so, could you provide me some pointers along that direction?
Moreover, I have a gfortran compiler installed in my system, Is there a way I could make use of it to complete my task mentioned above?
Furthermore, I tried to use mex to perform the same:
mckoctfile --mex HelloWorld.f
I got the following error after trying the mex approach:
c:/octave/octave~1.0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\rajan\AppData\Local\Temp/oct-qur1RF.o: in function `hi': C:\Tech Stuff\Fortran Programs/HelloWorld.f:3: undefined reference to `_gfortran_st_write'
c:/octave/octave~1.0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Tech Stuff\Fortran Programs/HelloWorld.f:3: undefined reference to `_gfortran_transfer_character_write'
c:/octave/octave~1.0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Tech Stuff\Fortran Programs/HelloWorld.f:3: undefined reference to `_gfortran_st_write_done'
c:/octave/octave~1.0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\rajan\AppData\Local\Temp/oct-qur1RF.o: in function `main':C:\Tech Stuff\Fortran Programs/HelloWorld.f:6: undefined reference to `_gfortran_set_args'
c:/octave/octave~1.0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Tech Stuff\Fortran Programs/HelloWorld.f:6: undefined reference to `_gfortran_set_options'
collect2.exe: error: ld returned 1 exit status
warning: mkoctfile: building exited with failure sta
How do I resolve this error to move forward?
Obviously your particular use-case may be a lot more complex than this, but here's a simple example to get you started (or to help you decide whether it's worth going down that route at all...)
Let's start with a simple octfile which performs simple integer addition, no fortran involved for now.
// in: simple_addition.cpp
#include <octave/oct.h>
DEFUN_DLD (simple_addition, args, ,"Add two integers via C++")
{
octave_value retval = args(0).int_value() + args(1).int_value();
return retval;
}
Compile:
mkoctfile -c simple_addition.cpp # compiles a simple_addition.o file
mkoctfile -o simple_addition simple_addition.o # links .o file to named output file
In octave:
octave:1> simple_addition(1,2)
ans = 3
Now let's put this aside for a minute, and see how we might call a fortran-defined function from pure c++. First let's create a simple integer addition function:
! in fortran_addition.f90
function fortran_addition(a,b) result(Out)
integer, intent(in) :: a,b ! input
integer :: Out ! output
Out = a + b
end function fortran_addition
and compile it using gfortran:
gfortran -c fortran_addition.f90 # creates fortran_addition.o
You can see (e.g. using nm fortran_addition.o) that the generated object contains a reference to a symbol under the name fortran_addition_ (note the added underscore at the end).
Now let's create a normal (i.e. non-octave-related) c++ wrapper program which calls the function defined via this symbol:
// in generic_fortran_addition_wrapper.cpp
#include <iostream>
extern "C" { int fortran_addition_( int *, int * ); }
int main() {
int a = 1, b = 2, fortran_result;
fortran_result = fortran_addition_( &a, &b );
std::cout << a << " + " << b << " = " << fortran_result << std::endl;
}
compile:
g++ -c generic_fortran_addition_wrapper.cpp
g++ -o addints generic_fortran_addition_wrapper.o fortran_addition.o
./addints # outputs `1 + 2 = 3` on the terminal
Now we have all the ingredients to create an octfile that wraps a fortran function:
// in fortran_addition_wrapper.cpp
#include <octave/oct.h>
extern "C" { int fortran_addition_( int *, int *); }
DEFUN_DLD (fortran_addition_wrapper, args, ,"Add two integers via fortran")
{
int a, b, fortran_result;
a = args(0).int_value();
b = args(1).int_value();
fortran_result = fortran_addition_( &a, &b );
octave_value retval(fortran_result);
return retval;
}
compile with mkoctfile:
mkoctfile -c fortran_addition_wrapper.cpp
mkoctfile -o fortran_addition_wrapper fortran_addition_wrapper.o fortran_addition.o
and then in octave:
octave:1> fortran_addition_wrapper(1,2)
ans = 3
Having said all this, obviously if you have a fully defined fortran program, rather than just linkable functions, and you have a running compiled executable on your system, then you can skip all the above 'formalities' and just call your executable via the system() command from octave. Obviously in this scenario it's up to you to pass the data in an octave-agnostic way ... but presumably if you have a standalone fortran executable, then presumably it already has a way of reading input data from the operating system.
EDIT as per the comments below, I've been reminded that I got side-tracked and answered the question that was asked in the comments to the original question, and forgot to address the error messages in the original question. As mentioned in my comment there, mkoctave is a generic wrapper to the gnu compiler collection. Those messages do not sound specific to octave, but rather that the compiler/linker complains that you're missing the fortran runtime libraries that define these basic functions.

Cannot convert string to char* for argument 1

I am having an issue with my C++ code for converting a string of numbers in base b to another base n. My error is as follows:
cannot convert ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ to ‘char*’ for argument ‘1’ to ‘int base_to_decimal(char*, int)’
I am using g++ to compile, and I have been for a while, so I thought at first I knew what the issue was. It says that the method base_to_decimal accepts two arguments: one of type char* and one of type int. So all I should have to do to fix my issue is change the char* argument to a string, right?
Well, I looked, and the code for the function in question is:
int base_to_decimal(std::string input_base, int base)
So this method SHOULD be expecting a string, but for some reason when I pass in a string, it gets angry at me.
If someone could help me figure this out, that would be fantastic. I am using g++ 7.3.0, and running all this on Linux Mint 19.1.
(EDIT)
Main Method
Functions
Table
You've written a custom declaration on line 46 of your main:
int base_to_decimal(char * input_base, int base)
But in the functions file where you've defined your function, you have:
int base_to_decimal(std::string input_base, int base)
This is why you should not write in-line declarations for external functions, but instead put the declarations in a header file. #include in the file where the function is later defined, ensures that the definition matches the declaration that the other files are expecting. And likewise, it enforces that all those other files are trying to use the function the way it's actually coded.

error: expected primary-expression before ')' token (C)

I am trying to call a function named characterSelection(SDL_Surface *screen, struct SelectionneNonSelectionne sel) which returns a void
This is the .h of the function I try to call:
struct SelectionneNonSelectionne;
void characterSelection(SDL_Surface *screen, struct SelectionneNonSelectionne);
void resetSelection(SDL_Surface *screen, struct SelectionneNonSelectionne);
On my main function, I try to call it like this:
characterSelection(screen, SelectionneNonSelectionne);
When I compile, I have the message:
error: expected primary-expression before ')' token
I made the includes. I suppose I miscall the second argument, my struct. But, I can't find why on the net.
Have you got any idea about what I did wrong?
You should create a variable of the type SelectionneNonSelectionne.
struct SelectionneNonSelectionne var;
After that pass that variable to the function like
characterSelection(screen, var);
The error is caused since you are passing the type name SelectionneNonSelectionne
A function call needs to be performed with objects. You are doing the equivalent of this:
// function declaration/definition
void foo(int) {}
// function call
foo(int); // wat!??
i.e. passing a type where an object is required. This makes no sense in C or C++. You need to be doing
int i = 42;
foo(i);
or
foo(42);
You're passing a type as an argument, not an object. You need to do characterSelection(screen, test); where test is of type SelectionneNonSelectionne.
I seen this problem with the latest nightly build of Code::Blocks. When I switched back to the stable release of Code::Blocks, 20.03 at the time of this writing, the problem went away and my code compiled and ran without problems. I'm not sure what Code::Blocks is doing, but it is very annoying. I got this repeatedly on a C++ project for every NULL in my code, forcing me to use nullptr instead.

C++ Invalid arguments using a function from class included from different file

I have the following decleration in file Order.h (Holdng class Order) :
void removeFromAlbum(int barcode);
and the following Implementation line:
void Order::removeFromAlbum(int barcode)
But, when im trying to call the function with a different file, Store.cpp (Order.h was included) with the following line :
order.removeFromAlbum(barcode);
I get the following error from eclipse :
Invalid arguments '
Candidates are:
void removeFromAlbum(int)
'
Eclipse is well defined.
Any suggestions ?
Edit :
This is the function when all the magic happens :
void Store::removeFromOrder(int ordNum, int barcode)
barcode is an int.
EDIT: Before the OP's edit, it was impossible to tell if barcode was an integer. This answer may, therefore, be invalid:
It looks like you're trying to call the function removeFromAlbum() with a type that isn't an int. Ensure that barcode is actually cast as an int.

How to create a glfw thread in c++?

I just started using glfw to try and built a game. I'm fairly new to C and C++ but I worked with openGL before for android. I have got all the openGL stuff working and now started to try and make a thread with glfw.
Here is some basic test code. Its similar to whats in the documentation.
#include <GL/glfw.h>
#include <stdio.h>
GLFWthread thread;
void GLFWCALL testThread()
{
printf("hello\n");
}
int main()
{
printf("test\n");
glfwInit();
thread = glfwCreateThread(testThread, NULL);
glfwWaitThread(thread, GLFW_WAIT);
glfwTerminate();
return 1;
}
This will compile fine in gcc and work as exspected.
$ gcc -o glthread glthread.c -lglfw
$ ./glthread
test
hello
The problem is i want to take advantage of c++ features like classes is my game. When I compile in g++ i get this...
$ g++ -o glthread glthread.c -lglfw
glthread.c: In function ‘int main()’:
glthread.c:18: error: invalid conversion from ‘void (*)()’ to ‘void (*)(void*)’
glthread.c:18: error: initializing argument 1 of ‘GLFWthread glfwCreateThread(void (*)(void*), void*)’
When i put it in a class the crucial error changes to this.
error: argument of type ‘void (Renderer::)()’ does not match ‘void (*)(void*)’
What I basically want to know is, is it possible to create threads using glfw in c++ and if so how?
My main PC for working on this is an arch linux machine. I can't give the versions of my compilers right now. If it will help I can get them later.
void GLFWCALL testThread()
{
printf("hello\n");
}
Should receive one argument of type void* and you cannot use class-functions here, since signature of pointer to class function is Ret (Class::*)(args), not void (*)(void*). If you want use pointers to class-members with threads - you should use more C++ style libraries (boost::thread, or something like it, or write your own wrapper).
Your example works in C, since in C empty brackets (i.e. () ) means - any number of parameters of any types, but in C++ () means, that function shouln't receive parameters at all.