ANSI C compile error: expected expression before ‘,’ token - c

I continue to get this error when attempting to compile a bit of code I wrote up, with the location in the file being totally unhelpful. This uses gtk 2.0.
The following is what I receive at compile time:
charles#draton-generico:~/Documents/C89$ gcc -x c -ansi -g bahbahbah.c -o bahbahbah pkg-config --cflags --libs gtk+-2.0
bahbahbah.c: In function ‘main’:
bahbahbah.c:28:1: error: expected expression before ‘,’ token
The following is the code I am trying to compile:
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
void closure(void)
{
gtk_main_quit();
printf("gtk_main_quit() has been called.\n");
}
void main(int argc, char* argv[])
{
gboolean check = gtk_init_check(&argc, &argv);
if (check == FALSE)
{
printf("Failed to initialize toolkit.\nTerminating.\n");
exit(EXIT_FAILURE);
}
else
{
printf("Initialized toolkit.\n");
GtkWidget* main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title((GtkWindow*)main_window, "BLAH");
gtk_window_set_default_size((GtkWindow*)main_window, 700, 700);
g_signal_connect(main_window, "delete-event", closure, void);
gtk_widget_show(main_window);
printf("Window created, sleeping in gtk_main().\n");
gtk_main();
}
printf("Exiting.\n");
exit(EXIT_SUCCESS);
}
Please help. :(

Use NULL replace void in line 28.
g_signal_connect(main_window, "delete-event", closure, NULL);

void is a Key-word!
There is the describe of g_signal_connect():
#define g_signal_connect(instance, detailed_signal, c_handler, data)
Connects a GCallback function to a signal for a particular object.
The handler will be called before the default handler of the signal.
instance :
the instance to connect to.
detailed_signal :
a string of the form "signal-name::detail".
c_handler :
the GCallback to connect.
data :
data to pass to c_handler calls.
Returns :
the handler id
So, you just want pass nothing to this func? Then you should use NULL.

Related

Setting the title of a Motif Window

I am trying to set the title of a toplevel Motif 2.1 window.
From O'Reilly Volume Six A, I have seen that in Motif 2.1 XtVaOpenApplication is recommended to create a toplevel Widget.
In this appendix it can be seen how options and XtNumber(options) are used to act on resources via argument list.
I have tried to use it to generate an optional flag -title WINDOW_TITLE while invoking the program, without sucess.
This is what I have tried:
#include <stdlib.h>
#include <stdio.h>
#include <Xm/Xm.h>
#include <Xm/PushB.h>
static XrmOptionDescRec options[] = {
{ "-title", "XmNtitle", XrmoptionIsArg, NULL },
};
int main(int argc, char *argv[]) {
Widget toplevel; /* Top Level Button */
XtAppContext app; /* Application Context */
char *window_title = NULL; /* Top Level Window Title */
/* INITIALIZE TOP LEVEL WINDOW */
XtSetLanguageProc(NULL, NULL, NULL);
toplevel = XtVaOpenApplication( &app, argv[0], options, XtNumber(options), &argc, argv, NULL, sessionShellWidgetClass, NULL);
/* REALIZE TOPLEVEL WINDOW AND LAUNCH APPLICATION LOOP */
XtRealizeWidget(toplevel);
XtAppMainLoop(app);
return 0;
}
The program compiles but it does not react to -title MYTITLE command line argument.
This is the makefile (works on FreeBSD 12):
test: test.o
cc -L/usr/local/lib -O -o test test.o -lXm -lXt -lX11
test.o: test.c
cc -I/usr/local/include -c test.c
How can I change the title of the window based on an optional argument named -title?
The correct xrm option line is
{"-title", ".title", XrmoptionSepArg, NULL}
You don't actually need to specify it because it is in the default Xt option table.
In general you omit XmN when specifying xrm resource names.
In my Motif programs, I use Xlib directly, since Motif does not seem to handle correctly the UTF8 setting of window titles using XmNtitle property. Most modern window managers expect UTF8 string passed as _NET_MW_NAME.
void setWindowTitleUTF8(Widget w, char *title)
{
static Atom atoms[3];
static bool first = TRUE;
if (first)
{
static char *atom_names[] = {"_NET_WM_NAME", "_NET_WM_ICON", "UTF8_STRING"};
first = FALSE;
XInternAtoms(XtDisplay(w), atom_names, 3, FALSE, atoms);
}
XChangeProperty(XtDisplay(w), XtWindow(w), atoms[_NET_WM_NAME], atoms[UTF8_STRING], 8,
PropModeReplace, (unsigned char *) title, strlen(title));
}
Make sure you call it on XtParent() of your widget, so it is applied to top level widget shell.
Please investigate further yourself (I'm no X/Motif expert), but sth seems to be off with the argument parsing.
Replacing options with NULL ant its size with 0 in call XtVaOpenApplication call seems to do the trick:
toplevel = XtVaOpenApplication( &app, argv[0], NULL, 0, &argc, argv, NULL, sessionShellWidgetClass, NULL);

Why am I getting segfault with loading objects from shared library?

Having this files:
plusone.c
int op(int i){ return i+1; }
main.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main(int argc, char **argv){
if (argc<3){
printf("usage %s <library> <number>\n",argv[0]);
exit(1);
}
char *lname = argv[1];
int num = atoi(argv[2]);
void *handle = dlopen(lname, RTLD_LAZY);
if(!handle)
perror("dlopen");
int (*opp)(int);
opp=dlsym(handle, "op");
if(!opp)
perror("dlsym");
printf("number before:%i\nnumber after:%i\n",num,opp(num));
dlclose(handle);
}
Compiled as:
$cc -fPIC -shared -o plusone.so -ldl plusone.c
$cc -o main.exe -ldl -Wpedantic main.c
warning: ISO C forbids assignment between function pointer and ‘void *’ [-Wpedantic]
$ls
main.c main.exe plusone.so main.exe
$main.exe
usage main.exe <library> <number>
$main plusone.so 1
dlopen: Success
dlsym: Success
Segmentation fault
Why is segfault?
As could be seen from the bash output, both the dlopen and dlsym give success (but they should not even output, otherwise that mean, the condition was true, and the returned values from those functions was NULL? - as from condition). But even of the "success" the perror returned, I cannot reproduce the segfault, since do not know where is the bug.
Why is segfault?
Most likely because opp equals NULL the moment opp(num) is trying to be called.
You do not handle errors correctly for the calls to dlopen() and dlysym(), although the code tests the results it does not take the correct actions on failure of those two functions.
This code
void *handle = dlopen(lname, RTLD_LAZY);
if(!handle)
perror("dlopen");
correctly branches on dlopen() returning NULL which indicated an error, but then the code takes the wrong actions.
dlopen() does not set errno, so using perror() to log an error makes no sense, as perror() relies on errno indicating an error, which is does not. So on failure of dlopen() you see perror() printing
dlopen: Success
which is misleading and contractionary to the fact that perror() was called at all, which in fact only happened if dlopen() returned NULL, indicating a failure. If dlopen() would have succeeded, perror() would not have been called at all and nothing would have been printed.
The same mistake appears with the call to dlsym().
To retrieve error info on failure of a member of the dl*() family of functions use dlerror().
For an example on how to correctly and completely implement error handling see below:
void *handle = dlopen(...);
if (!handle)
{
fprintf(stderr, "dlopen: %s\n", dlerror());
exit(EXIT_FAILURE); /* Or do what ever to avoid using the value of handle. */
}
#ifdef DEBUG
else
{
fputs("dlopen: Success\n", stderr);
}
#endif
The same approach should be taken to handle the outcome of dlsym().
Aside of all this and unrelated to the observed behaviour the code misses to call dlclose() when done with using a valid handle.

Is there a way to command during runtime to not to call a particular function (to comment it out) in C (Linux)?

I want to specify during run-time to ignore a function call for a function (which is of course defined) inside my executable. Please suggest some methodology for doing the same in C language on Linux.
Probably the best you can do is something like this:
// Filename mycode.c
int main()
{
// ...
#ifndef SOME_MACRO
someFUnction();
#endif
//...
}
int someFUnction()
{
// does something
}
To exclude the function call in main, you need to compile with
gcc -DSOME_MACRO mycode.c
If you will compile simply as
gcc mycode.c
then the function call will be enabled.
You cannot ignore function calls at runtime, you either call the function or you don't.
But let's assume for the sake of this answer that there exists a condition under which the function gets called and at least another condition under which the function is not called.
You can tell the program these conditions in several ways, for example per command-line, change of environment/file, and probably a long list more. For simplicity let's use the command-line and give the conditions in form of a argument to the executable. Additionally, because it is simple and short, use a signal.
File optional_functions.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
static void a(void)
{
puts("Function \"a\" called");
}
static void b(void)
{
puts("Function \"b\" called");
}
static void c(void)
{
puts("Function \"c\" called (by signal SIGINT)");
}
#include<signal.h>
#include<unistd.h>
static void signal_handler(int signal_number)
{
if (signal_number == SIGINT) {
c();
exit(EXIT_SUCCESS);
}
}
int main(int argc, char **argv)
{
void *dynlib;
void (*function_d) (void);
char *dynlib_error;
if (argc == 2) {
if (argv[1][0] == 'a') {
a();
} else if (argv[1][0] == 'b') {
b();
} else if (argv[1][0] == 'd') {
puts("External function \"d\" wanted, loading library");
dynlib = dlopen("libfunctiond.so", RTLD_LAZY);
if (dynlib == NULL) {
fprintf(stderr, "Failed loading lib: %s\n", dlerror());
exit(EXIT_FAILURE);
}
*(void **) (&function_d) = dlsym(dynlib, "d");
dynlib_error = dlerror();
if (dynlib_error != NULL) {
fprintf(stderr, "Failed calling function \"d\" fom lib: %s\n",
dynlib_error);
exit(EXIT_FAILURE);
}
(*function_d) ();
} else {
fprintf(stderr, "A function named \"%c\" does not exist, bailing out\n",
argv[1][0]);
exit(EXIT_FAILURE);
}
} else {
if (signal(SIGINT, signal_handler) == SIG_ERR) {
fprintf(stderr, "signal catching failed, bailing out\n");
exit(EXIT_FAILURE);
}
sleep(5);
puts("Signal catching timed out, assuming no function wanted in the first place.");
}
exit(EXIT_SUCCESS);
}
File functiond.h
#ifndef FUNCTIOND_H
#define FUNCTIOND_H
void d(void);
#endif
File functiond.c
#include <stdio.h>
#include "functiond.h"
void d(void)
{
puts("Function \"d\" called and says hello from the library");
}
Compile as
clang -Weverything -fPIC -c functiond.c
clang -shared -Wl,-soname,libfunctiond.so.1 -o libfunctiond.so.1.0 functiond.o
ln -sf libfunctiond.so.1.0 libfunctiond.so.1
ln -sf libfunctiond.so.1 libfunctiond.so
clang -Weverything -o optional_functions optional_functions.c example.c -ldl
Run it
$ ./optional_functions # waiting 5 seconds
Signal catching timed out, assuming no function wanted in the first place.
$ ./optional_functions # press CTRL+c in less than 5 seonds
^CFunction "c" called (by signal SIGINT)
$ ./optional_functions 1
A function named "1" does not exist, bailing out.
$ ./optional_functions a
Function "a" called
$ ./optional_functions b
Function "b" called
$ ./optional_functions d
External function "d" wanted, loading library
Failed loading lib: libfunctiond.so: cannot open shared object file: No such file or directory
That was expected. Either give dlopen() the complete path to the library or let the environment variable LD_LIBRARY_PATH do the job:
$ LD_LIBRARY_PATH=. ./optional_functions d
External function "d" wanted, loading library
Function "d" called and says hello from the library
It is not the proper way to make, install and and use dynamic libraries, of course, but again: for the sake of simplicity…

How to make libxml2 not display connection errors?

Consider the following code:
#include <stdio.h>
#include <libxml/parser.h>
int main(void) {
xmlDocPtr doc;
xmlChar *s;
doc = xmlParseFile("http://localhost:8000/sitemap.xml");
s = xmlNodeGetContent((struct _xmlNode *)doc);
printf("%s\n", s);
return 0;
}
The output:
$ gcc -g3 -O0 $(xml2-config --cflags --libs) 1.c
$ ./a.out
error : Operation in progress
<result of xmlNodeGetContent>
That is, xmlParseFile produces undesired output. What happens here is libxml2 tries to translate localhost to IP address. What it gets is ::1 and 127.0.0.1. connect("[::1]:8000") results in EINPROGRESS (since libxml2 sets O_NONBLOCK on the descriptor). So libxml2 waits for it to finish, which results in POLLOUT | POLLERR | POLLHUP, and libxml2 reports an error.
Subsequent connect("127.0.0.1:8000") call succeeds, so all in all the program finishes successfully.
Is there a way to avoid this extra output?
As suggested by nwellnhof, connection errors can be circumvented by setting error handler. Particularly, structured error handler, whatever that means.
While the answer in the other question more or less answers my question, that other question is about parser errors. And the answer doesn't provide example code. So,
#include <stdio.h>
#include <libxml/parser.h>
void structuredErrorFunc(void *userData, xmlErrorPtr error) {
printf("xmlStructuredErrorFunc\n");
}
void genericErrorFunc(void *ctx, const char * msg, ...) {
printf("xmlGenericErrorFunc\n");
}
int main(void) {
xmlDocPtr doc;
xmlChar *s;
xmlSetGenericErrorFunc(NULL, genericErrorFunc);
xmlSetStructuredErrorFunc(NULL, structuredErrorFunc);
doc = xmlParseFile("http://localhost:8000/sitemap.xml");
s = xmlNodeGetContent((struct _xmlNode *)doc);
printf("%s\n", s);
return 0;
}
This one outputs,
xmlStructuredErrorFunc
<result of xmlNodeGetContent>

Segmentation fault at GTK+ program

I am trying to make an example of a simple GTK+ viewer using poppler and cairo which I found at gtkforums.com work. However I am getting a segmentation fault (I use anjuta).
When I use the debugger I get this:
ID:1
File: /usr/lib/i386-linux-gnu/libgdk-x11-2.0.so.0
Line: 0
Function: ??
Address: 0x1d3f16 (dont think that matters anyway)
terminal message while debugging:
Debug Terminal for the process:
------------------------------- &"warning: GDB: Failed to set controlling terminal: Operation not permitted\n"
GLib-GObject-WARNING **: cannot register existing type `GdkWindow'
GLib-GObject-CRITICAL **: g_object_new: assertion `G_TYPE_IS_OBJECT
(object_type)' failed
Here is my code:
#include <config.h>
#include <glib/gi18n.h>
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <cairo.h>
#include <poppler.h>
/* gcc `pkg-config --cflags --libs gtk+-2.0 poppler-glib` -o pdfviewer pdfviewer.c */
static PopplerDocument* doc;
static PopplerPage* page;
static void
on_destroy(GtkWidget* w, gpointer data) {
gtk_main_quit();
}
static gboolean
on_expose(GtkWidget* w, GdkEventExpose* e, gpointer data) {
cairo_t* cr;
cr = gdk_cairo_create(w->window);
poppler_page_render(page, cr);
cairo_destroy(cr);
return FALSE;
}
int main(int argc, char* argv[]) {
GtkWidget* win;
GError* err = NULL;
gtk_init(&argc, &argv);
doc = poppler_document_new_from_file("file:///home/user/test.pdf", NULL, &err);
if (!doc) {
printf("%s\n", err->message);
g_object_unref(err);
return 2;
}
page = poppler_document_get_page(doc, 0);
if(!page) {
printf("Could not open first page of document\n");
g_object_unref(doc);
return 3;
}
int pages = poppler_document_get_n_pages(doc);
printf("There are %d pages in this pdf.\n", pages);
win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(on_destroy), NULL);
g_signal_connect(G_OBJECT(win), "expose-event", G_CALLBACK(on_expose), NULL);
gtk_widget_set_app_paintable(win, TRUE);
gtk_widget_show_all(win);
gtk_main();
g_object_unref(page);
g_object_unref(doc);
return 0;
}
Based upon your comment it ("Cannot access memory at address 0x0") appears that the program has a function that fails, but you didn't check the function's return value to ensure it is not NULL before using it.
Based purely on the code example above the first case of that would be if gtk_window_new failed; then the g_signal_connect and other functions cannot use the win value sensibly.
When I compiled the snippet, it compiled fine without warnings, and executed correctly. There was a poppler error message about the PDF document, but it wasn't relevant to your problems.
So your problem is likely either elsewhere (not within the included example) or a trivial mistake.
One way to get more information is to set a breakpoint on g_log in the debugger and get a backtrace of the warning / critical. With the backtrace you'll be able to see where exactly your code is calling the gtk+ function that is failing.

Resources