I am new at GTK programming and I am facing the following issue. I can compile the code without any warnings or errors however when I execute the binary I get this massage and the button does not work.
The error looks like this:
(project:9686): Gtk-WARNING **: 16:26:31.359: Could not find signal handler 'on_button_clicked'. Did you compile with -rdynamic?
That is the code:
#include <gtk/gtk.h>
static const gchar *interface =
"<interface>"
" <object class=\"GtkWindow\" id=\"main-window\">"
" <signal name=\"destroy\" handler=\"gtk_main_quit\"/>"
" <child>"
" <object class=\"GtkButton\" id=\"my-button\">"
" <property name=\"label\">Hallo, Welt!</property>"
" <signal name=\"clicked\" handler=\"on_button_clicked\"/>"
" </object>"
" </child>"
" </object>"
"</interface>";
G_MODULE_EXPORT void on_button_clicked (GtkWidget *w, gpointer d)
{
g_print ("Hallo, Welt!\n");
}
int main (int argc, char *argv[])
{
GtkBuilder *builder;
GError *error = NULL;
GtkWidget *window;
gtk_init (&argc, &argv);
builder = gtk_builder_new ();
gtk_builder_add_from_string (builder, interface, -1, &error);
gtk_builder_connect_signals (builder, NULL);
window = GTK_WIDGET(gtk_builder_get_object (builder, "main-window"));
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
I am working at a Linux machine and I compiled in the terminal with the following command:
g++ -Wall -std=c++0x project.cpp `pkg-config --cflags --libs gtk+-3.0 gmodule-2.0` -o project
I tried to compile with:
-rdynamic
-Wl,--export-dynamic
-lgmodule-2.0
pkg-config --cflags --libs gtk+-3.0 gmodule-no-export-2.0
but nothing worked.
It's hard to know for sure, but I would guess the problem is that you are compiling using a C++ compiler whereas your example is written in C. The C++ compiler is "mangling" the names of your exported symbols. If you aren't writing the rest of your program in C++, then I would recommend compiling with gcc -std=c99 instead of g++ -std=c++0x.
On the other hand, if the rest of your program does need to be written in C++, then you will need to prefix every symbol that you want to export for GtkBuilder (which does not know about C++ name mangling) with extern "C", or place them all together inside one or more extern "C" { ... } blocks. This will prevent the name from being mangled, so then GtkBuilder will be able to find it.
To check whether this is the case, try running nm -g | grep on_button_clicked (without any "demangle" option) on your compiled file. If the name is mangled, you will see something like __Z17on_button_clicked13BLAH14BLAH whereas if it is not, then you will just see _on_button_clicked.
Related
I am testing C code using googleTest.
My test.cpp file look like that
#include <gtest/gtest.h>
extern "C" {
#include "list.h"
#include "list.c"
}
TEST(ListTest, singleInsertion) {
// some tests
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
However trying to run the test from the terminal using
g++ test.cpp -lgtest gives Errors and warning as if the code being tested is C++ not C.
Error and warning Examples :
error: invalid conversion for mallocs and
warning: ISO C++ forbids converting a string constant to ‘char*'
how can I declare that my tested files are C not C++ ?
However trying to run the test from the terminal using g++ test.cpp -lgtest gives Errors and warning as if the code being tested is C++ not C.
That's because you are compiling it as C++ by using the g++ compiler. Use gcc to compile as C.
Unfortunately, this code won't compile as C - it'll choke on the google::InitGoogleTest() call because C doesn't recognize the :: scoping operator. I'm not familiar with this testing framework, but at first glance it looks like it's meant to be used with C++, not C.
The way to fix this is to remove the #include "list.c" directive
extern "C" {
#include "list.h"
}
and compile it separately as C:
gcc -c list.c
then compile your tester:
g++ -c test.cpp
and then link the object files with the library:
g++ -o test test.o list.o -lgtest
Including the following statement in my code
main_module->dump(); // main_module is of type llvm::Module*
causes the following linker error:
undefined reference to 'llvm::Module::dump() const'
The dump method resides in /usr/lib/llvm-5.0/include/llvm/IR/Module.h
I checked stack overflow (Using llvm::Function::dump(), linker gives "undefined reference to `llvm::Value::dump() const'"), and it seems we get this error when the linker isn't fed the libraries in correct order. However, I clearly have the libraries in the end in my compilation command:
clang++-5.0 -g -O3 main.cpp -o main llvm-config-5.0 --cxxflags --ldflags --system-libs --libs core mcjit native
Any help is appreciated.
The weird thing is, the linker figured out that the type of the dump method. It clearly went in the include file. So why would it call it an undefined reference?
Code I am trying to run:
`
# include "llvm/IR/LLVMContext.h"
# include "llvm/IR/Module.h"
# include "llvm/IR/IRBuilder.h"
# include <iostream>
using namespace llvm;
static LLVMContext ctxt;
static IRBuilder<> builder(ctxt);
int main(int argc, char** argv) {
Module* main_module = new Module("main_module", ctxt);
std::cout << main_module->getModuleIdentifier() << "\n";
FunctionType* func_type = FunctionType::get(builder.getInt32Ty(), false);
Function* main_func = Function::Create(func_type,Function::ExternalLinkage, "main", main_module);
if (main_module->getFunction("main")) {
std::cout << "Found function!\n";
}
main_module->dump(); // need this for debugging and testing reasons with LLVM
return 0;
}
In addition to the solution that Subrat provided, you can adjust your code to avoid calling dump. You can achieve the same thing by calling:
main_module->print(llvm::outs(), nullptr);
Similarly, if you want to dump a LLVM function, you can write:
main_func->print(llvm::outs());
Actually, as of LLVM 5.0.0, this is how the dump() function is implemented.
Seems like the definition for dump is in ASMWriter.cpp, which seems to be depracated.
Also, ASMWrite.cpp's debug method refers to dbgs() which is in debug.cpp
I fixed the problem by copying over debug.cpp and the Module::dump() (from ASMWriter.cpp--since I don't need the whole code, only a specific subroutine from this file) routine and putting it in my cpp file.
The C++ Standard indicates that the main can have two possible signatures.
int main() // (1)
int main(int, char*[]) // (2)
Moreover, main() is typically called from __libc_start_main, which is defined in csu/libc-start.c in the glibc source code. The invocation of main inside this function is copied below.
result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
We observe that the call here uses three arguments, and this appears to not produce any linker errors, despite the fact that the signature does not match either of the above two forms.
I am writing a threading library which defines main(), and would like the application to be able to define one of the following two functions.
int AppMain() // (1)
int AppMain(int, char*[]) // (2)
Unfortunately, if I declare AppMain using the second form above and invoke it from my library's main, and the application uses the first form instead, then I get a unresolved reference linker error indicating that the function I invoked does not exist.
Since this does not seem to be a problem for glibc with respect to main, how might I write my invocation or declaration in a way that avoids the linker error?
Here is an easy way to reproduce the problem.
Makefile
CCFLAGS=-Wall -Werror
all: libLib.a App
libLib.a: Lib.o
ar rcs $# $^
App: App.o libLib.a
g++ -o $# $< -L. -lLib
%.o: %.cc
g++ $(CCFLAGS) -O3 $(LIBS) -fPIC -c -o $# $<
Lib.cc
#include <stdio.h>
int AppMain(int argc, char** argv);
#undef main
int main(int argc, char** argv){
printf("Hello World\n");
AppMain(argc, argv);
}
App.cc (Working Version)
#include <stdio.h>
int AppMain(int argc, char** argv){
printf("Application says Hello world\n");
return 0;
}
App.cc (Non-Working Version)
#include <stdio.h>
int AppMain(){
printf("Application says Hello world\n");
return 0;
}
Under the second version, here is the linker error.
./libLib.a(Lib.o): In function `main':
Lib.cc:(.text.startup+0x24): undefined reference to `AppMain(int, char**)'
collect2: error: ld returned 1 exit status
Makefile:9: recipe for target 'App' failed
make: *** [App] Error 1
Regardless of suggestions to do it differently, I just answer your question
how might I write my invocation or declaration in a way that avoids the linker error?
You may write your definition in App.cc as
extern "C" int AppMain()
{
…
and your declaration in Lib.cc as
extern "C" int AppMain(int argc, char** argv);
to avoid that name mangling, the same as it's most probably done in glibc. There may be C++ compilers where this doesn't work, but it certainly works with the GCC.
I tried to compile a simple C++ program that uses SDL 2 with the mingw-w64-g++ compiler on my Arch Linux (64bits).
For this I downloaded SDL2-devel-2.0.4-mingw.tar.gz from here
prog.cpp:
#include <SDL.h>
int main ()
{
SDL_Init (SDL_INIT_VIDEO);
SDL_Window *sdlWnd = SDL_CreateWindow ("Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 800, 600, 0);
SDL_Event event;
bool running = true;
while (running) {
while (SDL_PollEvent (&event)) {
if (event.type == SDL_QUIT) {
running = false;
break;
}
}
}
return 0;
}
Makefile:
GPP = x86_64-w64-mingw32-g++
prog.exe: prog.o
$(GPP) -o prog.exe prog.o -LSDL2-2.0.4/lib/x64 -lSDL2main -lSDL2
prog.o: prog.cpp
$(GPP) -o prog.o -c -ISDL2-2.0.4/include prog.cpp
Now making gives the error:
x86_64-w64-mingw32-g++ -o prog.exe prog.o -LSDL2-2.0.4/lib/x64 -lSDL2main -lSDL2
Warning: corrupt .drectve at end of def file
SDL2-2.0.4/lib/x64/SDL2main.lib(./x64/Release/SDL_windows_main.obj):(.text[main]+0x1c): undefined reference to `SDL_main'
Why undefined reference to `SDL_main' ? Although I specified -lSDL2main ?
What did I do wrong? :(
Okay, it was because of the main functions signature, that has to be declared as:
int main(int argc, char *argv[])
according to the official SDL FAQ:
Make sure that you are declaring main() as:
#include "SDL.h"
int main(int argc, char *argv[])
You should be using main() instead of WinMain() even though you are
creating a Windows application, because SDL provides a version of
WinMain() which performs some SDL initialization before calling your
main code. If for some reason you need to use WinMain(), take a look
at the SDL source code in src/main/win32/SDL_main.c to see what kind
of initialization you need to do in your WinMain() function so that
SDL works properly.
How can I use either GCC or the Sublime IDE to compile my SDL based project on Linux?
gcc main.cpp -o main -lSDL2
I have tried this and I just get errors that seem to be pointing to the idea that either the program isn't pointing at the library the right way or the compiler isn't recognizing the library. On Sublime I have essentially done the same thing by creating my own build system for SDL, but it doesn't really seem to do anything at all. What might I be doing wrong?
{
"cmd" : [ "gcc", "$file", "-o", "-lSDL2" ]
{
I hope this question is appropriate on this stack, it can be considered Linux tooling but the Linux and Unix stack doesn't suggest programming questions unless they consist of shell scripting.
Here is just the basic Hello World that I am testing (Obviously not quite formatted correctly, but you get the idea.) :
#include <SDL2/SDL.h>
int main(int argc, char *argv[]) {
int win = 1;
SDL_Event event;
SDL_Init(SDL_INIT_EVERYTHING);
SDL_WM_SetCaption("Window", NULL);
SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
while (win) {
SDL_WaitEvent(&event);
if (event.type == SDL_QUIT)
win = 0;
}
SDL_Quit();
return 0;
}
When the program is compiled I use the GCC command posted at the top and get these errors:
main.cpp: In function ‘int main(int, char**)’:
main.cpp:19:37: error: ‘SDL_WM_SetCaption’ was not declared in this scope
SDL_WM_SetCaption("Window", NULL);
^
main.cpp:20:36: error: ‘SDL_HWSURFACE’ was not declared in this scope
SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
^
main.cpp:20:49: error: ‘SDL_SetVideoMode’ was not declared in this scope
SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
^
I have also tried pointing directly to header files in GCC with:
gcc main.cpp -o main -l/usr/include/SDL2
I did check to make sure that the header files were in usr/include/SDL2, maybe the actual library isn't installed in the right place for development?
The errors from GCC were cause by calling functions in SDL2 that didn't exist. Changing the previous SDL Video calls to:
SDL_CreateWindow(
"Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_OPENGL
);
was the right way to create a window in SDL 2;
Following with the GCC commands:
gcc main.cpp -o main -lSDL2
Compiled the code correctly and thus made it executable. Thank you for pointing that out #HolyBlackCat