Connect Postgresql in C - c

I'm trying to connect a C script running on Windows to my Postgresql database.
For the moment, I got this script on a website :
#include <stdio.h>
#include "libpq-fe.h"
#include <string>
#include <stdlib.h>
int main() {
PGconn *conn;
PGresult *res;
int rec_count;
int row;
int col;
conn = PQconnectdb("dbname=ljdata host=localhost user=dataman password=supersecret");
if (PQstatus(conn) == CONNECTION_BAD) {
puts("We were unable to connect to the database");
exit(0);
}
res = PQexec(conn,
"update people set phonenumber=\'5055559999\' where id=3");
res = PQexec(conn,
"select lastname,firstname,phonenumber from people order by id");
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
puts("We did not get any data!");
exit(0);
}
rec_count = PQntuples(res);
printf("We received %d records.\n", rec_count);
puts("==========================");
for (row=0; row<rec_count; row++) {
for (col=0; col<3; col++) {
printf("%s\t", PQgetvalue(res, row, col));
}
puts("");
}
puts("==========================");
PQclear(res);
PQfinish(conn);
return 0;
}
I copied the libpq-fe.h, the postgres_ext.c and the pg_config_ext.c to avoid the errors.
and now I have all this errors :
undefined reference to 'PQconnectdb'
undefined reference to 'PQresultStatus'
...
So obviously I don't have the file.c which contains all the functions I need but I can't find it.
I saw on another forum I need to create a makefile to tell the compiler to use the libpq.dll (I have this file) but I haven't the knowledge to do that.
How can I make this working ?
EDIT
So now when I try to compile it like that :
gcc -I "C:\Program Files\PostgreSQL\9.6\include" -L "C:\Program Files\PostgreSQL\9.6\lib" test.c -lpq
And I get the error :
C:\Program Files\PostgreSQL\9.6\lib/libpq.dll: file not recognized: File format not recognized
collect2.exe: error: ld returned 1 exit status
I think it's near to the final solution.
From the research I made, I found that libpq.dll is 32bit, but my environnement is 64bit. do this change anything ?
EDIT 2
The compilation now works correctly with this line :
gcc -m64 -I "C:\Program Files\PostgreSQL\9.6\include" -L "C:\Program Files\PostgreSQL\9.6\lib" test.c -lpq -o test.exe
But when I double-click on the .exe I have the following error :
"Unable to start the program because LIBPQ.dll is missing"
So it clearly means that I have to link the libpq.dll with probably a link to Program Files/PG/9.6/lib.
The problem here is that I want to build a standalone .exe which probably embed the Postgresql lib to works correctly even if the computer target haven't Postgresql installed on it
(This is possible, for example in Java when we build a Jar with all the external lib copied in)
Is it possible in C ? I think I need to adapt my compilation line but I don't found which parameter I can add to import all the needed lib in the .exe

From your edits I see that you have figured out how to use the -I and -L options of gcc by now. Good.
I guess your relaining problem is that you are trying to link with a 64-bit libpq.dll in 32-bit mode or vice versa.
You can set the mode with the gcc options -m32 and -m64.
You can examine the shared library with file libpq.dll, that should tell you if it is a 32-bit or a 64-bit library.
If gcc tells you something like: 64-bit mode not compiled in, you need to install an appropriate version of gcc.
To solve the problem that libpq.dll is not found at run time, either put the directory where it resides into the PATH environment variable, or use the option -Wl,-rpath,<directory with libpq.dll>.

Related

Undefined reference to (Quickmail)

I am looking for how to install quickmail.
I put quickmail.h here: C:\Program Files\CodeBlocks\MinGW\include, the .a and .la here: C:\Program Files\CodeBlocks\MinGW\lib.
I linked these .a files by adding them in the linker settings. I also did include the library like this: #include <quickmail.h>, but the functions are not recognized.
What should I do ?
The 4 files in the bin folder are in the project folder and I downloaded files from here : quickmail - Sourceforge.
EDIT : I get \main.c|9|undefined reference to '__imp_quickmail_initialize'| \main.c|10|undefined reference to '__imp_quickmail_create'| \main.c|11|undefined reference to '__imp_quickmail_set_body' and I put C:\Program Files\CodeBlocks\MinGW\include in search directories.
This is the code :
#include <stdio.h>
#include <stdlib.h>
#include <quickmail.h>
int main()
{
const char* error;
quickmail_initialize();
quickmail mailobj = quickmail_create("aaa#gmail.com", "libquickmail test e-mail");
quickmail_set_body(mailobj, "This is a test e-mail.\nThis mail was sent using libquickmail.");
quickmail_add_attachment_file(mailobj, "words.txt", NULL);
if ((error = quickmail_send(mailobj, "smtp.gmail.com", 587, "aaa#gmail.com", "MAGA2020")) != NULL)
fprintf(stderr, "Error sending e-mail: %s\n", error);
quickmail_destroy(mailobj);
return 0;
}
Sorry, the site gave me the wrong version.
To use a library you need to include the header in the code (in this case #include <quickmail.h>) and if needed tell the compiler where to find this file (the full path to the lib folder) with the -I compiler flag.
Next you need to tell the linker to link with the library (in this case -lquickmail or -lquickmaillight) and if needed where to find this file (the full path to the lib folder) with the -L linker flag.
Your errors are linker errors, so it seems the second step wasn't properly done.
In Code::Blocks it looks like this (though unlike the screenshots you should set it at the top-level instead of just for Debug builds):

undefined reference to `__imp_WSAStartup' in linux

Hi I want to build an application for windows in C, I program in linux and compile the code with gcc and mingw-w64.
I tried a simple program with output and input it works fine on windows.
But, I want to use sockets to connect to a server.
So I searched in google and found this tutorial http://beej.us/guide/bgnet/output/html/multipage/intro.html#audience
It says that in windows we need to include winsock and run some command
So I did:
#include <winsock.h>
int main(void)
{
WSADATA wsaData;
printf("Hello! This is a test prgoram.\n");
if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
fprintf(stderr, "WSAStartup failed.\n");
}
}
But when I try to compile it I get:
undefined reference to `__imp_WSAStartup'
collect2: error: ld returned 1 exit status
In command line all that I run was:
x86_64-w64-mingw32-gcc try.c -o a.exe
So what I should do?
If I compile in linux I don't need the winsock library?
How to fix this?
thanks
If you look at the WSAStartup Manual and scroll a bit down, you will find what library it is defined in: Ws2_32.lib
This is an "import library", a stub you need to link against for a windows program to use the respective DLLs. MinGW includes all standard windows platform import libraries. So you just need to link it, using -lws2_32.

Undefined reference and bad reloc address when linking to libsndfile

In a project project I am working on, I need to be able to open and read content from audio files (at least WAV files). I installed libsndfile using the Win64 installer from mega-nerd.com, and created a simple C program that opens and closes an audio file to test out the library.
#include <stdio.h>
#include <sndfile.h>
int main()
{
SNDFILE *sndfPtr;
SF_INFO soundfileInfo;
char path[] = "C:\\Users\\jayb\\Documents\\MusicClips\\violin.wav";
printf( "Path: %s\n", path );
/* Open soundfile for reading */
soundfileInfo.format = 0; /* Must be set to zero before opening */
sndfPtr = sf_open( path, SFM_READ, &soundfileInfo );
if( sndfPtr == NULL )
{
fprintf( stderr, "Error: %s\n", sf_strerror(NULL) );
return -1;
}
/* Close soundfile and check for error */
if( sf_close( sndfPtr ) )
{
fprintf( stderr, "There was an error closing the soundfile\n" );
return -1;
}
return 0;
}
However, I keep getting undefined reference errors to the libsndfile functions, plus a bad reloc address error when I try compiling/linking:
C:\Users\jbiernat\AppData\Local\Temp\ccSmO0dw.o:sndfile_test.c:(.text+0xbb): undefined reference to `sf_open'
C:\Users\jbiernat\AppData\Local\Temp\ccSmO0dw.o:sndfile_test.c:(.text+0xd8): undefined reference to `sf_strerror'
C:\Users\jbiernat\AppData\Local\Temp\ccSmO0dw.o:sndfile_test.c:(.text+0x10a): undefined reference to `sf_close'
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: C:\Users\jbiernat\AppData\Local\Temp\ccSmO0dw.o: bad reloc address 0x20 in section `.eh_frame'
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: final link failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
I'm compiling with this command:
gcc -Wall -o sndfile_test.exe sndfile_test.c -llibsndfile-1
The install of libsndfile comes with header files sndfile.h and sndfile.hh, and .lib, .def, and .dll files: libsndfile-1.lib libsndfile-1.def libsndfile-1.dll
The header and library directories are included in the compiler's search path, and it doesn't seem to be a problem of finding the library? I'm linking the .lib file with -llibsndfile-1 as per instructions on the minGW wiki
I also copied and renamed the .lib file with the .a extension and tried linking with -lsndfile-1 (this worked for someone else having a similar problem), but I get the exact same errors when I do so.
Any help would be appreciated! If I cannot link successfully to libsndfile, are there are any other simple libraries out there I could use for reading from audio files?
Edit: Of course I spend two days trying to find the solution, finally post to stackoverflow, and then solve the problem two hours later. I will post my solution as an answer to the question.
Following the information on this page of the MinGW wiki, use MinGW's dlltool with the libsndfile-1.def file to re-create the the dll's import library.
Use this command to do so:
dlltool -d libsndfile-1.def -l libsndfile-1.dll.a
This will create the .dll.a file that you can use instead of the .lib file. Note that when I did this, the .dll.a file did not appear in the directory I was in when I executed the above command. It ended up hidden in my \AppData directory, so you might have to search your OS for it.
Replace the libsndfile-1.lib in your lib directory with libsndfile-1.dll.a and then compile using:
gcc -Wall -o sndfile_test.exe sndfile_test.c -lsndfile-1

Tcl interpreter undefined reference error while compiling with gcc

I am new to Tcl scripting and would like to use C to embed Tcl codes.
This is the code that I have copied from a website to test the Tcl-C working.
test.c
#include <stdio.h>
#include <tcl.h>
void main ()
{
Tcl_Interp *myinterp;
char *action = "set a [expr 5 * 8]; puts $a";
int status;
printf ("Your Program will run ... \n");
myinterp = Tcl_CreateInterp();
status = Tcl_Eval(myinterp,action);
printf ("Your Program has completed\n");
getch();
}
I am using MinGW to compile this file.
I have copied the contents of the C:\Tcl\include folder into the C:\MinGW\include folder as well.
My gcc command for compiling :
gcc -o test.exe test.c
The error message shown :
C:\Users\user\AppData\Local\Temp\ccEHJKCb.o:tcl_connection_test.c:(.text+0x23): undefined reference to `_imp__Tcl_CreateInterp'
C:\Users\user\AppData\Local\Temp\ccEHJKCb.o:tcl_connection_test.c:(.text+0x3d): undefined reference to `_imp__Tcl_Eval'
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: C:\Users\user\AppData\Local\Temp\ccEHJKCb.o: bad reloc address 0x20 in section `.eh_frame'
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: final link failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
I don't seem to have any libtcl file in the Tcl folder.
The Tcl version is ActiveTcl 8.5.15.0.297577.
Any help would be really appreciated.
Your example how to embed Tcl is outdated, and you are missing certain things in your link line (-ltcl85 for example). If you simply add -ltcl85 to your link line it should start to work.
It does not work in your case, because you installed the x64 (64-Bit version) of ActiveTcl, which provides x64 dlls, not 32-Bit ones. But the standard mingw gcc only works with 32-Bit libraries.
So to get this to work:
Download the 32-Bit ActiveTcl distribution
Compile your code with gcc -o test.exe test.c -Lc:/tcl/lib -Ic:/tcl/include -ltcl86
Adjust your path so the c:\tcl\bin\tcl86.dll is found in PATH, make also sure Tcl finds its libdir (set TCL_LIBRARY=c:\tcl\lib\tcl8.6)
run your program
But for more complex examples, you still need to initialise the library and a do some boilerplate code, so please call Tcl_FindExecutable(argv[0]); before the call to Tcl_CreateInterp() otherwise a few commands (e.g. clock might just not work as expected).
Have a look at http://www.tcl.tk/cgi-bin/tct/tip/66.html for some more details. Also have a look at the Tcl source distribution and the source for the tclsh shell.
You're very close to getting it right.
The Tcler's Wiki has a few examples, some of which are very confusing to be frank, but this one from this page is the best I've spotted recently. (The comments are mine.)
#include <stdlib.h>
#include <tcl.h>
int main (int argc, char *argv[]) {
Tcl_Interp *interp;
const char *script = "proc p1 a { puts $a }";
// Initialize the Tcl library; ***STRONGLY RECOMMENDED***
Tcl_FindExecutable(argv[0]);
// Create the interpreter, the execution context
interp = Tcl_CreateInterp();
// Initialise the interpreter
if (TCL_OK != Tcl_Init(interp)) {
fprintf(stderr, "Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
exit(EXIT_FAILURE);
}
// Define a procedure
Tcl_Eval(interp, script);
fprintf(stderr, "res 1: %s\n", Tcl_GetStringResult(interp));
// Check if the procedure exists
Tcl_Eval(interp, "puts [info commands p*]");
fprintf(stderr, "res 2: %s\n", Tcl_GetStringResult(interp));
// Call the procedure
Tcl_Eval(interp, "p1 abc");
fprintf(stderr, "res 3: %s\n", Tcl_GetStringResult(interp));
// We could use Tcl_DeleteInterpreter to clean up here, but why bother?
return EXIT_SUCCESS;
}
What else were you missing? Simple. You forgot to tell the C compiler to use the Tcl library when building the executable; the compiler (or, more strictly, the linker) is in places a stupid piece of code. The exact option to use to get the linker to add the library in will depend on your system configuration, but is probably going to be -ltcl, -ltcl8.5 or -ltcl8.6; which it is depends on the filename and all sorts of things that we can't check exactly without being on your system. The names do fit a simple pattern though.
It's also possible that you might need to pass the -L option in to tell the linker about additional library locations. (There's an equivalent -I for telling the compiler where to find include files, so you don't have to copy everything into one gigantic unmanageable directory.)
The order of arguments can matter. Libraries should be listed after the source file:
gcc -o test.exe test.c -L/mingw/path/to/library/directory -ltcl86
(If you're using old, unsupported versions of Tcl — why would you do that?! — then the code above won't work because Tcl_Eval then took a writable string. But that was fixed many years ago and upgrading to a current version is the fix.)

Combine C and TCL using Swig

I have been following a tutorial to combine C with TCL using Swig. The tutorial seemed to be properly working but at the end I ran into an error that I cannot solve. The situation is as follows:
The tutorial I was following is:
http://www.swig.org/tutorial.html.
I have a file named test.c:
char *HelloWorld()
{
return "hello world";
}
and another named test.i:
%module test
%{
/* Put header files here or function declarations like below */
extern char *HelloWorld();
%}
extern char *HelloWorld();
I then used the following command line arguments to ready the correct files:
gcc -c test.c -o test.o
swig -tcl test.i
gcc -c test_wrap.c -o test_wrap.o
gcc -dynamiclib -framework Tcl test.o test_wrap.o -o test.so
And finally I tried to load it using:
tclsh
% load test.so test
This is the point where I received the following error:
dlsym(0x100600090, Test_Unload): symbol not founddlsym(0x100600090, Test_SafeUnload): symbol not found
As far as I know I did not stray from the tutorial. Can anyone tell me how it is that I got this error and more importantly how to get rid of it?
Thanks in advance!
Are those error messages stopping the load from working? They shouldn't; they're reporting that the low-level API for supporting unloading of the extension isn't present, but that's OK (lots of extensions can't be unloaded; it's tricky to write code that supports it).
You don't mention exactly which version of Tcl you are using — but it must be at least 8.5 for those symbols to be even searched for in the first place — so it is a little hard to guess what the exact underlying issue is. (The message should simply not be reported.) I advise filing a bug report on this; make sure you include all exact versions in your report.
It's a long time since I used SWIG, so I'm not sure whether it gives you sufficient control over the code it generates for you to be able to apply this fix. Glossing over that detail, I can reproduce (and fix) the issue with the following:
In 'ext.c':
#include <tcl.h>
int DLLEXPORT Ext_Init(Tcl_Interp *interp) {
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
if (Tcl_PkgProvide(interp, "Ext", "0.0") == TCL_ERROR) {
return TCL_ERROR;
}
return TCL_OK;
}
Build, run tclsh, load extension:
$ gcc -dynamiclib -framework Tcl ext.c -o ext.so
$ tclsh8.5
% load ./ext.so
dlsym(0x400000, Ext_SafeInit): symbol not found
dlsym(0x400000, Ext_Unload): symbol not found
dlsym(0x400000, Ext_SafeUnload): symbol not found
Something internal to the library loading code is putting that error message into the interpreters result. To stop the message ever surfacing, set or reset the result so that the _Init() function ends with one or other of:
// Set the result to a message of your choosing
Tcl_SetObjResult(interp, Tcl_NewStringObj("ok", -1));
// Or clear out the result altogether
Tcl_ResetResult(interp);
return TCL_OK;
}
The init block feature of swig might insert code in the right place to achieve the same thing:
%init %{
Tcl_ResetResult(interp);
%}

Resources