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.
Related
I'm writing software to control a bladeRF radio card but I'm running into a strange compiler/linker error that I haven't been able to figure out. My code uses several functions and data structures defined in the library, libbladeRF, but for some reason I can't reference to one specific function.
However, if I modify the call with an improper argument type, g++ will throw an error to let me know that it doesn't conform to the definition, which seems to tell me that the linker is actually able to locate the reference.
What am I missing?
Initial error:
$ g++ bladeRF_test.cpp -o bladeRF_test -lbladeRF
/tmp/ccTWZzdJ.o: In function `enable_xb300()':
bladeRF_test.cpp:(.text+0x36a): undefined reference to `bladerf_xb300_set_amplifier_enable'
Code excerpt:
#include <iostream>
#include <string>
#include <libbladeRF.h>
using namespace std;
...
int set_xb300_pa(bool enable) {
bladerf_xb300_amplifier amp = BLADERF_XB300_AMP_PA;
if ( bladerf_xb300_set_amplifier_enable(dev, amp, enable) ) {
// Print error message
return -1;
} else {
// Print success message
return 0;
}
}
...
Function arguments changed from (dev, amp, enable) to (&dev, amp, enable):
$ g++ blade_hello.cpp -o blade_hello -lbladeRF
blade_hello.cpp: In function ‘int set_xb300_pa()’:
blade_hello.cpp:62:59: error: cannot convert ‘bladerf**’ to ‘bladerf*’ for argument ‘1’ to ‘int bladerf_xb300_set_amplifier_enable(bladerf*, bladerf_xb300_amplifier, bool)
^
In file included from blade_hello.cpp:4:0:
/usr/local/include/libbladeRF.h:2226:15: note: declared here
int CALL_CONV bladerf_xb300_set_amplifier_enable(struct bladerf *dev,
^
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.
I've been learning C++ and using the Terminal for the last couple of months. My code was compiling and running fine using g++ and C++11, but in the last couple of days it started giving errors and I have had problems compiling since. The only programs I can compile and run depend on older C++ standards.
The errors I first got related to #include < array > in the header file. Not sure why this happened, but I got around it by using boost/array instead. Another error I can't solve is with std::stoi. Both array and stoi should be in the C++11 standard library. I made the following simple code to demonstrate what's going on:
//
// stoi_test.cpp
//
// Created by ecg
//
#include <iostream>
#include <string> // stoi should be in here
int main() {
std::string test = "12345";
int myint = std::stoi(test); // using stoi, specifying in standard library
std::cout << myint << '\n'; // printing the integer
return(0);
}
Try to compile using ecg$ g++ -o stoi_trial stoi_trial.cpp -std=c++11
array.cpp:13:22: error: no member named 'stoi' in namespace 'std'; did you mean
'atoi'?
int myint = std::stoi(test);
~~~~~^~~~
atoi
/usr/include/stdlib.h:149:6: note: 'atoi' declared here
int atoi(const char *);
^
array.cpp:13:27: error: no viable conversion from 'std::string' (aka
'basic_string') to 'const char *'
int myint = std::stoi(test);
^~~~
/usr/include/stdlib.h:149:23: note: passing argument to parameter here
int atoi(const char *);
^
2 errors generated.
I also get these errors at compilation when using gcc or clang++ and with -std=gnu++11 (I guess they all depend on the same file structure). I also get the same error whether I specify std:: in the code, or if I specify using namespace std;
I worry that these issues arose because of the September Command Line Tools update via Xcode or because I installed boost and this somehow messed up my C++11 libraries. Hopefully there is a simple solution.
My system:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-> dir=/usr/include/c++/4.2.1
Apple LLVM version 5.0 (clang-500.2.76) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix
Thanks for any insight you can offer.
clang has a weird stdlib, you need to add the following flag when you compile
-stdlib=libc++
your snippet works on my mac with
g++ -std=gnu++11 -stdlib=libc++ test.cpp -o test
This answer describes the problem
The program should get arguments from a command line, and add the arguments via posix threads. But Xcode successfully builds it, but gives no output. Is there something wrong with this code.
Thanks
#include <iostream>
#include <pthread.h>
using namespace std;
void *Add(void *threadid){
long tid;
tid =(long)threadid;
long sum=0;
sum=sum+tid;
printf("%ld.\n",sum);
pthread_exit(NULL);
}
void *Print(void *threadid){
long tid;
tid =(long)threadid;
printf("%ld.\n",tid);
pthread_exit(NULL);
}
int main (int argc, char const *argv[])
{
if(argc<6){
printf("you need more arguments");
return -1;
}
long real[5];
pthread_t athread,bthread;
for (int x=1;x<=5;x++)
real[x-1]=atol(argv[x]);
for(int y=1;y<=5;y++)
pthread_create(athread[y],NULL,Add,(void *)&real[y]);
for(int y=1;y<=5;y++)
pthread_create(bthread[y],NULL,Print,(void *)&real[y]);
pthread_exit(NULL);
return 0;
}
First of all I think you should check if pthread_create method was success.
I don't have expirience in pthread under Apple, but based on that code I think you have problem with thread creation.
First of all, printf is defined in stdio.h and not in iostream. If you'd like to do it the C++ way with iostream, then cout << "Blabla " << var << endl; should be used instead.
Second, you are calling pthread_create with wrong arguments. As defined athread and bthread are not arrays but you use them as such. I am not entirely sure why this would even compile since pthread_create expects pthread_t* as first argument and you are providing *pthread_t. If the code ever compiles, it will most likely crash when run.
Third, you are not joining the adder threads. This means that your print threads could start before the adder threads have finished.
Fourth, you are summing into local variables. You are supposed to sum into a global one. Don't forget to guard the access to it by a mutex or something.
Fifth, arguments to the thread routines are wrong. You are passing pointer to the value and not the value itself and later reinterpreting the pointer as the value itself. You would most likely want to use (void *)real[y] and not (void *)&real[y]. Mind that casting long to void * doesn't work on all systems. On Mac OS X both long and void * are of the same length (either 32 or 64 bits) but this is not true in general.
Edited: Your code doesn't even compile on OS X:
$ g++ -o t.x t.cpp
t.cpp: In function ‘int main(int, const char**)’:
t.cpp:37: error: cannot convert ‘_opaque_pthread_t’ to ‘_opaque_pthread_t**’ for argument ‘1’ to ‘int pthread_create(_opaque_pthread_t**, const pthread_attr_t*, void* (*)(void*), void*)’
t.cpp:40: error: cannot convert ‘_opaque_pthread_t’ to ‘_opaque_pthread_t**’ for argument ‘1’ to ‘int pthread_create(_opaque_pthread_t**, const pthread_attr_t*, void* (*)(void*), void*)’
$ clang -o t.x t.cpp
t.cpp:37:5: error: no matching function for call to 'pthread_create'
pthread_create(athread[y],NULL,Add,(void *)&real[y]);
^~~~~~~~~~~~~~
/usr/include/pthread.h:304:11: note: candidate function not viable: no known
conversion from 'struct _opaque_pthread_t' to 'pthread_t *' (aka
'_opaque_pthread_t **') for 1st argument;
int pthread_create(pthread_t * __restrict,
^
t.cpp:40:5: error: no matching function for call to 'pthread_create'
pthread_create(bthread[y],NULL,Print,(void *)&real[y]);
^~~~~~~~~~~~~~
/usr/include/pthread.h:304:11: note: candidate function not viable: no known
conversion from 'struct _opaque_pthread_t' to 'pthread_t *' (aka
'_opaque_pthread_t **') for 1st argument;
int pthread_create(pthread_t * __restrict,
^
2 errors generated.
Don't you even see the error messages that XCode is providing?
Refactoring legacy code, I came across this function (pseudocode):
int getMessage( char * buffer, int size = 300 );
Gee, look at that buffer just waiting to overflow. So I came up with a function using std::string, and thought it would be nice to use function overloading:
int getMessage( std::string & buffer );
So far, so good. But when I try to call the function with a string:
std::string buffer;
int rc = getMessage( buffer );
I get this error:
cannot convert 'std::string' to 'char*' for argument '1' to 'int getMessage(char*, int)'
Obviously, the compiler (GCC 4.1.2) tries hard to convert std::string to char* to satisfy the first function's parameter list (using the default value to satisfy the second parameter), gives up, but doesn't try the second function...
I wouldn't have a problem working around this issue, but I'd like to know why this fails, and whether there would be a way to make it work as intended.
It works as expected on my GCC 4.3.2, maybe you misspelled the name of the overload? There's no conversion from std::string to char*, so the compiler shouldn't have any problems choosing the correct overload.
$ cat test.cpp
#include <string>
#include <stdio.h>
int getMessage( char * buffer, int size = 300 )
{
printf("1\n");
return 1;
}
int getMessage( std::string & buffer )
{
printf("2\n");
return 2;
}
int main()
{
std::string buffer;
buffer = "Hello";
int rc = getMessage( buffer );
}
$ g++ test.cpp -Wall -pedantic
test.cpp: In function ‘int main()’:
test.cpp:20: warning: unused variable ‘rc’
$ ./a.out
2
$ $ g++ -v 2>&1|tail -n1
gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)
$
Hmmm. There is no implicit conversion from std::string to char*, so that can't be your problem. Are you sure your new function is visible at the call site?
You said this is pseudo-code. Are you leaving something out? Are these template functions or member functions? Please post more of the code or try to boil it down to a smaller test case.
My guess is that the overload for the string version of the function isn't visible where you called it. Are you sure that it is in the correct header file, and is spelled correctly?
Do you have a declaration of `int getMessage( std::string & buffer );' in scope? You are hitting this error because the proper function is not being found.
As always, once the problem is solved, the solution is painfully trivial and should have been obvious all along.
So I came up with a function using std::string...
...in my working directory, which compiled just fine, but -I and -L in my makefile were still pointing at the previous version of the library, which was blissfully unaware of the new function.
Sorry for the bother. I've been an idiot. I hope this doesn't become a habit. ;-)