I needed wanted to build "did you mean this?" feature to my website. I'm using sqlite3 and learned that i can use spellfix module to order tables via levenstein.
I downloaded source code of sqlite3 and compiled spellfix.c (it's inside /ext/misc/) like this:
gcc -shared -fPIC -Wall -I/tmp/sqlite-src-3071700/ spellfix.c -o spellfix
It compiles successfuly but when i load it into sqlite:
sqlite> .load ./spellfix
I'm getting this error:
Error: ./spellfix: undefined symbol: sqlite3_extension_init
I really have very few knowledge about compiling c programs. Did i do some mistake about compiling or something else is happened? What should i do?
It seems the sqlite init function is missing. There is a discussion here http://sqlite.1065341.n5.nabble.com/SQLite-version-3-7-16-td67776.html
I added the following code at the top.
static int spellfix1Register(sqlite3 *db);
int sqlite3_extension_init(sqlite3 *db, char ** pxErrMsg, const sqlite3_api_routines *pApi){
SQLITE_EXTENSION_INIT2(pApi);
return spellfix1Register(db);
}
Also needed the following since I couldn't pull in the headers for the sqlite3_stricmp function without creating additional problems:
int sqlite3_stricmp(const char *zLeft, const char *zRight){
return strcasecmp(zLeft, zRight);
}
And needed this too:
#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8))
Then it compiled and seemed to function correctly.
Related
Sorry for the simple question. I am attempting to learn more c++ at a fundamental level. I have always used VS in the past, and I am trying to learn the command line and compile, navigate, etc. with it.
I started with "hello world" and was able to compile it with gcc/clang, then run it with the expected results.
I then slightly reworked this and made a new header/cpp file to do the output part of hello world, and then call that from the main function, described below:
main.cpp:
#include "MyClass.h"
int main(){
foo();
return 0;
}
MyClass.h
#pragma once
void foo();
MyClass.cpp
#include "MyClass.h"
#include <iostream>
void foo(){
std::cout << "Hello World\n";
}
I then have tried to compile with gcc and clang as follows:
clang -Wall -g main.cpp MyClass.cpp
I have tried the same with GCC, and have also tried various invocations of this, such as using -c:
clang -Wall -g -c main.cpp
clang -Wall -g -c MyClass.cpp
Each and every time, I get an error
λ clang -Wall -g MyClass.cpp main.cpp
main.cpp:13:1: error: use of undeclared identifier 'foo'
foo();
^
1 error generated.
I get this same error whether using gcc or clang.
I also tried from scratch on my laptop, to see if there was some more global issue, but I still get the same problem.
I have also tried on the basic Windows command line as well.
Other areas on StackOverflow demonstrate simple ways of compiling multiple files from the command line, and I have tried as they show, but still get errors.
I also know that "make" is something I need to learn as well, however, I just want to make sure I understand what my make file is doing before I dive into that.
I feel like it must be something trivial that I just cannot figure out.
Thank you to Andreas for the suggestion of looking at the preprocessor output. And thank you to everyone for the suggestions.
The pre-processor output did not make sense to what I was compiling.
I was using VSCode, in this case, as a text editor, making brand new files in my folder after launching it from the command line. I thought the files I created in VSCode directly into the folder (named main.cpp, for example), would produce a regular text file. However, for some reason, it did not.
Essentially, I recreated the above program in notepad and was easily able to compile it using the commands I used above. I guess VSCode may not be perfect for me as a pure text editor or I should figure out if there are settings to change to accomplish my goal.
Thank you all again for your time and consideration.
Use extern on your function. Also make sure you're compiling with c++ and not c; i.e. g++.
MyClass.h
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
extern void foo();
#ifdef __cplusplus
}
#endif
I'm trying to port the lhslib library (written in C++) to WebAssembly using emscripten (emcc v. 1.40.1, clang v. 12.0.0, macOS 10.15.5). Unfortunately I have a very limited understanding of C++, so please bear with me.
So far, I forked the repo, created a build folder, and from there started to try and convert the randomLHS.cpp file to WASM:
// a short overview of what the file looks like
#include "LHSCommonDefines.h"
#include "utilityLHS.h"
namespace lhslib
{
void randomLHS(int n, int k, bclib::matrix<int> & result, bclib::CRandom<double> & oRandom)
{
// further contents of the file
}
}
Running
emcc ../src/lhslib/randomLHS.cpp -I../src/bclib -o randomLHS.html
creates the expected files randomLHS.wasm ,randomLHS.js, and randomLHS.html.
However, when serving the html file and inspecting the Module object created by emscripten, it does not contain the desired randomLHS function.
I then read about the EXPORTED_FUNCTIONS option and proceeded to try the following
emcc ../src/lhslib/randomLHS.cpp -I../src/bclib -o randomLHS.html -s EXPORTED_FUNCTIONS='["_randomLHS"]' -s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]'
This results in the following error:
emcc: error: undefined exported function: "_randomLHS" [-Wundefined] [-Werror]
Unfortunately I couldn't find any examples showcasing how to export a namespace (as in the randomLHS file), or how to specify a function from the namespace that should be exported.
Could you guide me on how I could achieve this?
Thanks for you help!
So according to the emscripten docs on using ccall and cwrap:
These methods can be used with compiled C functions — name-mangled C++ functions won’t work.
I believe there are other ways to do this; check out WebIDL Binder and Embind.
I have an embedded application that has been written for gcc 3.2.31, and I want to link a library, written by myself, and compiled using g++ 7.2.0.
I have already built and link a test library with almost no code, but now that I am trying something more relevant, I face some issues regarding undefined symbols. Currently, I have the following kind of errors:
undefined reference to __assert_func
I do not get this error if I compile using g++ 3.2.3.
I want to use g++ 7.2.0 to have access to the new C++14 (maybe C++17) features and some new parts of the standard library (std::chrono::duration, etc.).
Is there a way to make this work?
I can fix the above issue by defining my own __assert_func:
extern "C" void __assert(const char *, int, const char *);
extern "C" void __assert_func(
const char *file, int line, const char *, const char *e) {
__assert(file, line, e);
}
...but I was wondering if there is a simpler way? In particular, there may be other name changes and I do not want to have to modify these everytime...
I assume I will not use new features that would require code that is not in the old gcc version (e.g., std::thread or std::chrono::system_clock).
Related:
Linking against an old version of libc to provide greater application coverage, with "solutions" for dynamic libraries, but no better solutions than mine for static libraries (i.e., rewriting the missing symbols).
1 The application and the library are built using the sparc-rtems gcc toolchains, and some third party tools such as JamaicaVM. I cannot simply change the toolchain used to build the main application because there are many incompatibilities with the new compiler toolchain...
I am attempting to use sqlite3 in a C++ project in Eclipse and have found a great deal of advice online on using the API, but unfortunately am falling at an earlier hurdle. I guess this is due to my lack of experience with C/C++ and CDT.
I've simply copied sqlite3.c and sqlite3.h into the project's source folder and have a test method which is as follows:
int main() {
sqlite3* db;
sqlite3** dbpointer = &db;
const char* dbname = "test.db";
sqlite3_open(dbname, dbpointer);
return 0;
}
However, the sqlite3.c file shows up in Eclipse with numerous errors. For example, the following section is annotated with 'Field 'IN_DECLARE_VTAB' could not be resolved'.
#ifdef SQLITE_OMIT_VIRTUALTABLE
#define IN_DECLARE_VTAB 0
#else
#define IN_DECLARE_VTAB (pParse->declareVtab)
#endif
When I try to compile I get a series of errors like:
gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/sqlite3.d" -MT"src/sqlite3.d" -o "src/sqlite3.o" "../src/sqlite3.c"
../src/sqlite3.c:30997: error: initializer element is not constant
../src/sqlite3.c:30997: error: (near initialization for `aSyscall[0].pCurrent')
../src/sqlite3.c:30997: error: initializer element is not constant
../src/sqlite3.c:30997: error: (near initialization for `aSyscall[0]')
../src/sqlite3.c:31009: error: initializer element is not constant
../src/sqlite3.c:31009: error: (near initialization for `aSyscall[1]')
../src/sqlite3.c:31017: error: initializer element is not constant
../src/sqlite3.c:31017: error: (near initialization for `aSyscall[2]')
I did find a similar question here, but it doesn't appear to have been resolved there either.
I suspect this is a set-up issue with Eclipse, so if anyone could give me any advice or directions to useful tutorials I'd really appreciate it. And if I'd be better off posting this to a dedicated sqlite forum just let me know.
SQLite is written in C, and there are a number of differences between C and C++. Not huge numbers, but they're definitely not the same and neither is a superset of the other. Because you are using a single Eclipse project, you've probably ended up trying to compile C code with a C++ compiler, and are therefore coming unstuck on these small differences.
You are advised to build sqlite3.c into a separate library (it can be a static library or a dynamic one; your call) as a C project, and then make your C++ project just use that C project as a dependency. Or you can build it once and just have it as an external dependency; that'll work too. (To be fair, it's an external dependency; you shouldn't really embed it wholesale into your code anyway as that will make tracking bugfixes harder. Keeping it separate — at least for build, even if not for distribution — will make your life much easier.)
Have you try in this way? (with double pointer):
int main() {
sqlite3* db;
const char* dbname = "test.db";
sqlite3_open(dbname, &db);
return 0;
}
I suppose you're working on linux.
Another approach is to execute a script:
int main() {
system("connectDB.sh");
/* connectDB.sh should be chmod +x */
}
Your file connectDB will be:
#!/bin/bash
sqlite3 test.db "select * from test.table"
I am facing a unique problem as part of our application migration from HP to AIX.
The following simulated code produces different results in HP and AIX.
library.C **
#include <stdio.h>
#include "mylib.h"
int libimgclientFNXXX()
{
int check = 100;
check = FileNetDeleteDoc(check);
return check;
}
int libimgclientFN()
{
int check = 1;
printf("In lib ");
return check;
}
* main_func.C *
#include <stdio.h>
int libimgclientFN();
int libimgclientFNXXX();
int main()
{
int one = 0;
if (1 == 1)
{
one = libimgclientFN();
}
printf("\n The status is %d \n", one);
}
* mylib.h **
extern int FileNetDeleteDoc (int);
Note that the function libimgclientFNXXX() is never called.
My make file is as below:
xlC -c -g library.C -o library.o -I./
xlC -G -qmkshrobj -o libImgClient.so library.o
xlC -c -g -qpic=small main_func.C -o main_func.o
xlC -brtl main_func.o -L. -lImgClient -o TST
When I run TST, I get the following loading error
$ TST
exec(): 0509-036 Cannot load program TST because of the following errors:
rtld: 0712-001 Symbol FileNetDeleteDoc__Fi was referenced
from module ./libImgClient.so(), but a runtime definition
of the symbol was not found.
Even though the function libimgclientFNXXX() is never called, there is unresolved errors.
The exact same code built in HP works fine with no errors.
Any inputs is appreciated.
Thanks,
Yeah, "not using" a library function may still be an error, even if you are not going to call the code. It MAY defer the loading of some componanent until later, so it MAY not cause an error. Best not to have references to things that don't exist (or manually load the library and get the address, if the function doesn't exist, you'll get an error from the "find the function" call and you can do something sensible in the code).
The loader (the code that loads binary executables) isn't very clever, so it can't know exactly what is being called and what isn't. It's also possible that different compilers have different levels of cleverness for "dead code removal", so the one compiler completely removes the "never called" function, but another compiler doesn't remove it [because it's not got the cleverness to 100% certify that you never call the function - in gcc for example, it would know this if you made the libimgclientFNXXX a static function - because it knows that static functions don't get called outside this module, and this module isn't using it.
AIX requires all symbols to resolve at load-time, so even though it builds OK, because the symbol is referenced the applications will not run.
You need to use lazy linking for the .so (the -blazy link option), which should cause the missing function to be linked only on first use.
You really should not be leaving undefined symbols in a library, though - if it needs symbols from another library, you should be linking to them (unless it's a plug-in, where the symbol is exposed in the app itself).