Mongodb C driver with my program - c

I had dl the Mongodb-c-driver from github.com, and compile it without problem, however, while I try to compile my C program, problem occurs:
testmongo.c:(.text+0x20): undefined reference to 'mongo_client'
testmongo.c:(.text+0x80): undefined reference to 'mongo_destroy'
I have link the mongodb library in ldconfig, however, this situation don't change...
#include <stdio.h>
#include <mongo.h>
int main() {
mongo conn[1];
int status = mongo_client( conn, "127.0.0.1", 27017 );
if( status != MONGO_OK ) {
switch ( conn->err ) {
case MONGO_CONN_NO_SOCKET: printf( "no socket\n" ); return 1;
case MONGO_CONN_FAIL: printf( "connection failed\n" ); return 1;
case MONGO_CONN_NOT_MASTER: printf( "not master\n" ); return 1;
}
}
mongo_destroy( conn );
return 0;
}
Could anyone Help?
Thank you very much !!!

I guess I should submit this as an answer until more information is given. On a hunch, you might be missing -lmongoclient from your gcc command.
gcc -o myprog -lmongoclient source.c

Related

"undefined reference" errors while using tidy library, especially "tidy.h"

I'm currently using a script which validates an invalid XML file or string using tidy library.
A sample code to test it's running:
#include <tidy.h>
#include <tidybuffio.h>
#include <stdio.h>
#include <errno.h>
int main(int argc, char **argv )
{
const char* input = "<title>Foo</title><p>Foo!";
TidyBuffer output = {0};
TidyBuffer errbuf = {0};
int rc = -1;
Bool ok;
TidyDoc tdoc = tidyCreate(); // Initialize "document"
printf( "Tidying:\t%s\n", input );
ok = tidyOptSetBool( tdoc, TidyXhtmlOut, yes ); // Convert to XHTML
if ( ok )
rc = tidySetErrorBuffer( tdoc, &errbuf ); // Capture diagnostics
if ( rc >= 0 )
rc = tidyParseString( tdoc, input ); // Parse the input
if ( rc >= 0 )
rc = tidyCleanAndRepair( tdoc ); // Tidy it up!
if ( rc >= 0 )
rc = tidyRunDiagnostics( tdoc ); // Kvetch
if ( rc > 1 ) // If error, force output.
rc = ( tidyOptSetBool(tdoc, TidyForceOutput, yes) ? rc : -1 );
if ( rc >= 0 )
rc = tidySaveBuffer( tdoc, &output ); // Pretty Print
if ( rc >= 0 )
{
if ( rc > 0 )
printf( "\nDiagnostics:\n\n%s", errbuf.bp );
printf( "\nAnd here is the result:\n\n%s", output.bp );
}
else
printf( "A severe error (%d) occurred.\n", rc );
tidyBufFree( &output );
tidyBufFree( &errbuf );
tidyRelease( tdoc );
return rc;
}
on running
gcc -I/usr/include/tidy tidy_example.c
I get this output on my terminal:
/tmp/cclFfP4I.o: In function main':
tidy_exa.c:(.text+0x6e): undefined reference totidyCreate'
tidy_exa.c:(.text+0x9e): undefined reference to tidyOptSetBool'
tidy_exa.c:(.text+0xba): undefined reference totidySetErrorBuffer'
tidy_exa.c:(.text+0xd6): undefined reference to tidyParseString'
tidy_exa.c:(.text+0xeb): undefined reference totidyCleanAndRepair'
tidy_exa.c:(.text+0x100): undefined reference to tidyRunDiagnostics'
tidy_exa.c:(.text+0x11f): undefined reference totidyOptSetBool'
tidy_exa.c:(.text+0x149): undefined reference to tidySaveBuffer'
tidy_exa.c:(.text+0x1a6): undefined reference totidyBufFree'
tidy_exa.c:(.text+0x1b2): undefined reference to tidyBufFree'
tidy_exa.c:(.text+0x1be): undefined reference totidyRelease'
collect2: error: ld returned 1 exit status
Any Idea as to how to resolve this issue, or any other library to do the same thing on a file or a string (invalid XML) in c/c++.
Any suggestions will also be welcomed.
You forgot to link the lib using -l option.
For example
gcc -I/usr/include/tidy -ltidy tidy_example.c -o example
If you also need to specify a specific folder for libs you must add -L option like
gcc -I/usr/include/tidy -L/usr/local/lib/tidy -ltidy tidy_example.c -o example

Asterisk:undefined reference to `SQLAllocHandle'

I added a test.c in asterisk/main directory to test ODBC. Unfortunately it shows like below when I run make.
test.o: In function `test_function':
/usr/src/asterisk-certified-13.8-cert3/main/libtest.c:10:
undefined reference to `SQLAllocHandle'
test.c like this:
#include "asterisk/res_odbc.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
int test_function(void){
int res;
SQLHANDLE output_handle;
res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &output_handle);
if ( (res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) ) {
ast_log(LOG_DEBUG, "AllocHandle Success!\n");
} else {
ast_log(LOG_WARNING, "Error AllocHandle");
}
return 0;
}
How can I fix this? Thanks!
You should change Makefile for include libs into your module.
But that is WRONG method when you working with asterisk.
Correct method is user REALTIME or func_odbc and make it care about connection.

Get current execution path from within C library

I'm writing a logger library in C and am currently trying to get better backtrace output by using addr2line. In order to do so, I need to be able to get the path of the current executable. At the moment I am just concerned about linux, but will be shooting for Mac OS support as well.
For linux support I'm trying to use readlink() and /proc/self/exe to resolve the current executable's path:
static char** getPrettyBacktrace( void* addresses[], int array_size ) {
// Used to return the strings generated from the addresses
char** backtrace_strings = (char**)malloc( sizeof( char ) * array_size );
for( int i = 0; i < array_size; i ++ ) {
backtrace_strings[i] = (char*)malloc( sizeof( char ) * 255 );
}
// Will hold the command to be used
char* command_string = (char*)malloc( 255 );
char* exe_path = (char*)malloc( 255 );
// Used to check if an error occured while setting up command
bool error = false;
// Check if we are running on Mac OS or not, and select appropriate command
char* command;
#ifdef __APPLE__
// Check if 'gaddr2line' function is available, if not exit
if( !system( "which gaddr2line > /dev/null 2>&1" ) ) {
command = "gaddr2line -Cfspe";
// TODO: get path for mac with 'proc_pidpath'
} else {
writeLog( SIMPLOG_LOGGER, "Function 'gaddr2line' unavailable. Defaulting to standard backtrace. Please install package 'binutils' for better stacktrace output." );
error = true;
}
#else
// Check if 'addr2line' function is available, if not exit
if( !system( "which addr2line > /dev/null 2>&1" ) ) {
command = "addr2line -Cfspe";
if( readlink( "/proc/self/exe", exe_path, sizeof( exe_path ) ) < 0 ) {
writeLog( SIMPLOG_LOGGER, "Unable to get execution path. Defaulting to standard backtrace." );
error = true;
}
} else {
writeLog( SIMPLOG_LOGGER, "Function 'addr2line' unavailable. Defaulting to standard backtrace. Please install package 'binutils' for better stacktrace output." );
error = true;
}
#endif
// If an error occured, exit now
if( error ) {
free( backtrace_strings );
free( command_string );
free( exe_path );
return NULL;
}
for( int i = 0; i < array_size; i++ ) {
// Compose the complete command to execute
sprintf( command_string, "%s %s %X", command, exe_path, addresses[i] );
// Execute the command
FILE* line = popen( command_string, "r" );
// Get the size of the command output
int line_size = fseek( line, 0, SEEK_END );
// Read the output into the return string
fgets( backtrace_strings[i] , line_size, line );
// Close the command pipe
pclose( line );
}
return backtrace_strings;
}
The path being returned by readlink() is: /home/nax��?. the first part is correct: /home/na, but everything after that is pure gibberish.
Why am I unable to get the current execution path in this way?
char* exe_path = (char*)malloc( 255 );
// ...
readlink( "/proc/self/exe", exe_path, sizeof( exe_path ) )
exe_path is a pointer, so it's size will be equal to sizeof(char*) (4 or 8), not 255.
change exe_path to char[255] or change the call to sizeof
btw, readlink does not append the NULL byte, so you should do something like this:
len = readlink( "/proc/self/exe", exe_path, sizeof( exe_path ) )
exe_path[len] = 0;

what is return error value of mysql_query in C?

folks,
from the following code
int a = mysql_query(conn,"INSERT into data VALUES (NULL,'tes','aja'));
how come i could make sure mysql_query is do the supposed thing, because i've tried wrong sql query and it becomes same return value
from mysql_query function which from file mysql.h:
int STDCALL mysql_query(MYSQL *mysql, const char *q);
is there a way to check that string of query is valid and queried properly ?
According to the MySQL reference documentation for mysql_query this should return zero on success and non-zero on failure. Are you sure that it is returning 0 value for an invalid query?
I was surprised that the MySQL database I had to use did not return error on "wrong query". (The MySQL database is not in my administration) You do not write what exact problem do you have with you query; what is the problem. I suppose my problem can be similar to your problem.
(Example table is simplified.)
My table 'T' with cols 'A' varchar[10] not null, 'B' varchar[10]
int a = mysql_query(conn,"INSERT INTO T (B) VALUE ('data')");
The problem is that the result is OK, error message is empty and only one warning is present.
Solution is to test not only error but also warnings.
if ( mysql_errno( conn ) || mysql_warning_count( conn ) )
result = 1; //error
else
result = 0; //OK
If you need to display warnings/errors there is my simple sample code:
static void display_warnings( MYSQL *conn )
{
MYSQL_RES *sql_result;
MYSQL_ROW row;
if ( ( conn == NULL ) || mysql_query( conn, "SHOW WARNINGS" ) )
{
printf( "Can not display list of errors/warnings!\n" );
return;
}
sql_result = mysql_store_result( conn );
if ( ( sql_result == NULL ) || ( sql_result->row_count == 0 ) )
{
printf( "Can not display list of errors/warnings!\n" );
if ( sql_result )
mysql_free_result( sql_result );
return;
}
row = mysql_fetch_row( sql_result );
if ( row == NULL )
{
printf( "Can not display list of errors/warnings!\n" );
mysql_free_result( sql_result );
return;
}
do
{
// Format: "message [Type: number]"
printf( "%s [%s: %s]\n", row[2], row[0], row[1] );
row = mysql_fetch_row( sql_result );
} while ( row );
mysql_free_result( sql_result );
}
I need to handle that all given data must be correct and none is missing. Missing data (according to table definition) is unacceptable; trimming of data ('ABC12345678' changed to 'ABC1234567') is also unacceptable. Both these problems are handled only as warning. Therefore I handle all warnings as errors.

Can I use regex_t for several compilations

Basic question, not clear to me for the regcomp man.
If I have a static instance of regex_t, can I reuse it for several compilation without freeing it every time, something like:
int match(char* pattern, char* name) {
static regex_t re;
regcomp(&re,pattern,REG_EXTENDED|REG_NOSUB);
...
}
The code itself is bit more complicated, and the idea is to use static variable to save compilation if the pattern was not changed between calls. The question is if I need to call regfree before each new regcomp.
Thanks.
If you want to use the previous result of regcomp() that was compiled into re that's perfectly fine - as long as you don't call regfree() in the meantime.
But when you want to compile a new regex by calling regcomp() again, you'll need to call regfree() to properly release any resources used by the previous regcomp() call. So you'll probably need some other static variable that keeps track of whether or not the re variable has been used by a call to regcomp() and needs to be regfree()-ed before being reused.
Something along the lines of:
int match(char* pattern, char* name) {
static regex_t re;
static int re_in_use = 0;
if (isNewRegex( pattern)) { // however you want to determine this...
if (re_in_use) {
regfree( &re);
re_in_use = 0;
}
}
re_in_use = regcomp(&re,pattern,REG_EXTENDED|REG_NOSUB);
...
}
Sorry, I cant write a good explanation, but here is an example code for a one element regcomp() cache:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <regex.h>
static struct {
char *pattern;
regex_t re;
} last_match = { .pattern = (char*)NULL };
int match( const char *pattern, const char *name ){
int ret;
if( last_match.pattern != (char*)NULL && strcmp( last_match.pattern, pattern ) != 0 ){
free( last_match.pattern ); last_match.pattern = (char*)NULL;
regfree( &last_match.re );
}
if( last_match.pattern == (char*)NULL ){
last_match.pattern = (char*)malloc( strlen(pattern)+1 );
strcpy( last_match.pattern, pattern );
ret = regcomp( &last_match.re, last_match.pattern, REG_EXTENDED|REG_NOSUB );
printf("regcomp: %i '%s'\n", ret, last_match.pattern );
}
ret = regexec( &last_match.re, name, 0, (regmatch_t*)NULL, 0);
printf("regexec: %i\n", ret );
return ret;
}
int main(void){
match( "[0-9]+", "qwer1234" );
match( "[0-9]+", "asdf5678" );
match( "[a-z]+", "qwer1234" );
match( "[a-z]+", "asdf5678" );
}
If You run the code You will see two 'regcomp' message and four 'regexec' message because of the regex_t reuse.

Resources