Problems with linking a library with a c program in linux - c

I want to run serial commands from a Bealgebone to a 4Dsystems display. Therefore I copied the c library found here into a directory and created a test program main.c:
#include "Picaso_const4D.h"
#include "Picaso_Serial_4DLibrary.h"
int main(int argc,char *argv[])
{
OpenComm("/dev/ttyUSB0", B115200); // Matches with the display "Comms" rate
gfx_BGcolour(0xFFFF);
gfx_Cls();
gfx_CircleFilled(120,160,80,BLUE);
while (1) {}
}
Now when I do gcc -o main main.c its says
main.c:2:37: fatal error: Picaso_Serial_4DLibrary.h: No such file or
directory
So I try linking it:
gcc main.c -L. -lPICASO_SERIAL_4DLIBRARY
which gives me the same error. Then I tried to create a static library:
gcc -Wall -g -c -o PICASO_SERIAL_4DLIBRARY PICASO_SERIAL_4DLIBRARY.C
which gives me this:
PICASO_SERIAL_4DLIBRARY.C:1:21: fatal error: windows.h: No such file
or directory compilation terminated.
What am I doing wrong? the git page clearly says this library is created for people who do not run windows.
Thanks in advance!

You're not getting a linker error; you're getting a preprocessor error. Specifically, your preprocessor can't find Picaso_Serial_4DLibrary.h. Make sure that it's in your include path; you can add directories to your include path using the -I argument to gcc.

You've had two problems. First was the picaso_whatever.h file that couldn't be found. You fixed that with the -I you added. But, now, the picaso.h wants windows.h
What are you building on? WinX or BSD/Linux?
If you're compiling on WinX, you need to install the "platform sdk" for visual studio.
If you're using mingw or cygwin, you need to do something else.
If on WinX, cd to the C: directory. Do find . -type f -name windows.h and add a -I for the containing directory.
If under Linux, repeat the find at the source tree top level. Otherwise, there is probably some compatibility cross-build library that you need to install.
Or, you'll have to find WinX that has it as Picaso clearly includes it. You could try commenting out one or more of the #include's for it and see if things are better or worse.
If you can't find a real one, create an empty windows.h and add -I to it and see how bad [or good] things are.
You may need the mingw cross-compiler. See https://forums.wxwidgets.org/viewtopic.php?t=7729
UPDATE:
Okay ... Wow ... You are on the right track and close, but this is, IMO, ugly WinX stuff.
The primary need of Picaso is getting a serial comm port connection, so the need from within windows.h is [thankfully] minimal. It needs basic boilerplate definitions for WORD, DWORD, etc.
mingw or cygwin will provide their own copies of windows.h. These are "clean room" reimplementations, so no copyright issues.
mingw is a collection of compile/build tools that let you use gcc/ld/make build utilities.
cygwin is more like: I'd like a complete shell-like environment similar to BSD/Linux. You get bash, ls, gcc, tar, and just about any GNU utility you want.
Caveat: I use cygwin, but have never used mingw. The mingw version of windows.h [and a suite of .h files that it includes underneath], being open source, can be reused by other projects (e.g. cygwin, wine).
Under Linux, wine (windows emulator) is a program/suite that attempts to allow you to run WinX binaries under Linux (e.g. wine mywinpgm).
I git cloned the Picaso library and after some fiddling, I was able to get it to compile after pointing it to wine's version of windows.h
Picaso's OpenComm is doing CreateFile [a win32 API call]. So, you'll probably need cygwin. You're opening /dev/ttyUSB0. /dev/* implies cygwin. But, /dev/ttyUSB0 is a Linux-like name. You may need some WinX-style name like "COM:" or whatever. Under the cygwin terminal [which gives you a bash prompt], do ls /dev and see what's available.
You can get cygwin from: http://cygwin.com/ If you have a 64 bit system, be sure to use the 64 bit version of the installer: setup-x86_64.exe It's semi-graphical and will want two directories, one for the "root" FS and one to store packages. On my system, I use C:\cygwin64 and C:\cygwin64_packages--YMMV.
Note that the installer won't install gcc by default. You can [graphically] select which packages to install. You may also need some "devel" packages. They have libraries and .h files that a non-developer wouldn't need. As, docs mention, you can rerun the installer as often as you need. You can add packages that you forgot to specify or even remove ones that you installed that you don't need anymore.
Remember that you'll need to adjust makefile -I and/or -L option appropriately. Also, when building the picaso library, gcc generated a ton of warnings about overflow of a "large integer". The code was doing:
#define control_code -279
unsigned char buf[2];
buf[0] = control_code >> 8;
buf[1] = control_code;
The code is okay, and the warning is correct [because the code is sloppy]. If the code had done:
#define control_code -279
unsigned char buf[2];
buf[0] = (unsigned) control_code >> 8;
buf[1] = (unsigned) control_code;
it probably would have been silent. Use -Wno-overflow in your Makefile to get rid of the warnings rather that edit 50 or so lines

Related

C - error: conflicting types for 'SDL_main' [duplicate]

I want to make a game using SDL2, but I'm unable to compile and/or run my code, please help!
SDL2 is notoriously hard to set up, and it's often the first library aspiring game developers try to use.
This post is intended as a canonical duplicate for common problems with setting up SDL2.
This answer is about MinGW / GCC, and not Visual Studio.
This answer only applies to Windows.
Common errors
The common errors are:
SDL.h: No such file or directory (when compiling)
Various SDL_main problems: "undefined reference to SDL_main", "conflicting types for SDL_main" or "number of arguments doesn't match prototype", etc. (when compiling or linking)
undefined reference to other functions (when linking)
DLL problems: (when running your program)
'??.dll' was not found
procedure entry point ... could not be located in ..., and other mysterious DLL-related errors
The program seemingly doing nothing when launched
This list is sorted from bad to good. If you change something and get a different error, use this list to tell if you made things better or worse.
The preamble
0. Don't follow bad advice.
Some resources will suggest you to do #define SDL_MAIN_HANDLED or #undef main. Don't blindly follow that advice, it's not how SDL2 is intended to be used.
If you do everything correcty, it will never be necessary. Learn the intended approach first. Then you can research what exactly that does, and make an educated decision.
1. Figure out how to compile directly from the console, you can start using an IDE and/or build system later.
If you're using an IDE, I suggest to first make sure you're able to compile your program directly from the console, to rule out any IDE configuration problems. After you figure that out, you can use the same compiler options in your IDE.
The same applies to build systems, such as CMake.
2. Download the right SDL2 files. Make sure you have the right files. You need the archive called SDL2-devel-2.0.x-mingw.tar.gz from here.
Extract it to any directory, preferably somewhere near your source code. Extracting into the compiler installation directory is often considered a bad practice (and so is copying them to C:\Windows, which is a horrible idea).
3. Know the difference between compiler flags and linker flags. A "flag" is an option you specify in the command line when building your program. When you use a single command, e.g. g++ foo.cpp -o foo.exe, all your flags are added to the same place (to this single command).
But when you build your program in two steps, e.g.:
g++ foo.cpp -c -o foo.o (compiling)
g++ foo.o -o foo.exe (linking)
you have to know which of the two commands to add a flag to. Those are "compiler flags" and "linker flags" respectively.
Most IDEs will require you to specify compiler and linker flags separately, so even if you use a single command now, it's good to know which flag goes where.
Unless specified otherwise, the order of the flags doesn't matter.
SDL.h: No such file or directory
Or any similar error related to including SDL.h or SDL2/SDL.h.
You need to tell your compiler where to look for SDL.h. It's in the SDL files you've downloaded (see preamble).
Add -Ipath to your compiler flags, where path is the directory where SDL.h is located.
Example: -IC:/Users/HolyBlackCat/Downloads/SDL2-2.0.12/x86_64-w64-mingw32/include/SDL2. Relative paths work too, e.g. -ISDL2-2.0.12/x86_64-w64-mingw32/include/SDL2.
Note that the path will be different depending on how you write the #include:
If you do #include <SDL.h>, then the path should end with .../include/SDL2 (like above). This is the recommended way.
If you do #include <SDL2/SDL.h>, then the path should end with .../include.
Various SDL_main problems
You can get several different errors mentioning SDL_main, such as undefined reference to SDL_main, or conflicting types for 'SDL_main', or number of arguments doesn't match prototype, etc.
You need to have a main function. Your main function must look like int main(int, char **). NOT int main() and NOT void main(). This is a quirk of SDL2, related to it doing #define main SDL_main.
Adding parameter names is allowed (and is mandatory in C), e.g. int main(int argc, char **argv). Also the second parameter can be written as char *[] or with a name: char *argv[]. No other changes are allowed.
If your project has multiple source files, make sure to include SDL.h in the file that defines the main function, even if it doesn't otherwise use SDL directly.
Try to avoid #define SDL_MAIN_HANDLED or #undef main when solving this issue, see preamble for explanation.
undefined reference to various functions
• undefined reference to SDL_...
The error message will mention various SDL_... functions, and/or WinMain. If it mentions SDL_main, consult the section "Various SDL_main problems" above. If the function names don't start with SDL_, consult the section "undefined reference to other functions" below.
You need to add following linker flags: -lmingw32 -lSDL2main -lSDL2 -Lpath, where path is the directory where libSDL2.dll.a and libSDL2main.a (which you've downloaded) are located. The order of the -l... flags matters. They must appear AFTER any .c/.cpp/.o files.
Example: -LC:/Users/HolyBlackCat/Desktop/SDL2-2.0.12/x86_64-w64-mingw32/lib. Relative paths work too, e.g. -LSDL2-2.0.12/x86_64-w64-mingw32/lib.
When you use -l???, the linker will look for a file called lib???.dll.a or lib???.a (and some other variants), which is why we need to pass the location of those files. libmingw32.a (corresponding to -lmingw32) is shipped with your compiler, so it already knows where to find it.
I added all those flags and nothing changed, or I'm getting skipping incompatible X when searching for Y:
You probably use the wrong SDL .a files. The archive you downloaded contains two sets of files: i686-w64-mingw32 (32-bit) and x86_64-w64-mingw32 (64-bit). You must use the files matching your compiler, which can also be either 32-bit or 64-bit.
Print (8*sizeof(void*)) to see if your compiler is 32-bit or 64-bit.
Even if you think you use the right files, try the other ones to be sure.
Some MinGW versions can be switched between 32-bit and 64-bit modes using -m32 and -m64 flags (add them to both compiler and linker flags).
I get undefined reference to a specific function:
• undefined reference to WinMain only
There are several possibilities, all of which were covered in the previous section:
You forgot -lmingw32 and/or -lSDL2main linker flags.
You must use following linker flags, in this exact order, after
any .c/.cpp/.o files: -lmingw32 -lSDL2main -lSDL2
The libSDL2main.a file you use doesn't match your compiler (32-bit file with a 64-bit compiler, or vice versa).
Try to avoid #define SDL_MAIN_HANDLED or #undef main when solving this issue, see preamble for explanation.
• undefined reference to SDL_main only
See the section "Various SDL_main problems" above.
• undefined reference to other functions
Your linker found and used libSDL2.a, but it should be finding and using libSDL2.dll.a. When both are available, it prefers the latter by default, meaning you didn't copy the latter to the directory you passed to -L.
If you intended to perform static linking, see the section called "How do I distribute my app to others?" below.
Nothing happens when I try run my app
Let's say you try to run your app, and nothing happens. Even if you try to print something at the beginning of main(), it's not printed.
Windows has a nasty habit of not showing some DLL-related errors when the program is started from the console.
If you were running your app from the console (or from an IDE), instead try double-clicking the EXE in the explorer. Most probably you'll now see some DLL-related error; then consult one of the next sections.
??.dll was not found
Copy the .dll mentioned in the error message, and place it next to your .exe.
If the DLL is called SDL2.dll, then it's in the SDL files you've downloaded (see preamble). Be aware that there are two different SDL2.dlls: a 32-bit one (in the i686-w64-mingw32 directory), and a 64-bit one (in x86_64-w64-mingw32). Get the right one, if necessary try both.
Any other DLLs will be in your compiler's bin directory (the directory where gcc.exe is located).
You might need to repeat this process 3-4 times, this is normal.
For an automatic way of determining the needed DLLs, see the next section.
procedure entry point ... could not be located in ... and other cryptic DLL errors
Your program needs several .dlls to run, and it found a wrong version of one, left over from some other program you have installed.
It looks for DLLs in several different places, but the directory with the .exe has the most priority.
You should copy all DLLs your program uses (except the system ones) into the directory where your .exe is located.
A reliable way to get a list of needed DLLs is to blindly copy a bunch of DLLs, and then remove the ones that turn out to be unnecessary:
Copy SDL2.dll. It's in the SDL files you've downloaded (see preamble). Be aware that there are two different SDL2.dlls: a 32-bit one (in the i686-w64-mingw32 directory), and a 64-bit one (in x86_64-w64-mingw32). Get the right one, if necessary try both.
Copy all DLLs from your compiler's bin directory (the directory where gcc.exe is located).
Now your program should run, but we're not done yet.
Download NTLDD (or some other program that displays a list of used DLLs). Run ntldd -R your_program.exe.
Any DLL not mentioned in its output should be removed from the current directory. Your program uses everything that remains.
I ended up with following DLLs, expect something similar: SDL2.dll, libgcc_s_seh-1.dll, libstdc++-6.dll (C++ only), libwinpthread-1.dll.
Can I determine the needed DLLs without copying excessive ones?
Yes, but it's less reliable.
Your program searches for DLLs in following locations, in this order:
The directory where your .exe is located.
C:\Windows, including some of its subdirectories.
The directories listed in PATH.
Assuming you (or some jank installer) didn't put any custom DLLs into C:\Windows, adding your compiler's bin directory to the PATH (preferably as the first entry) and either putting SDL2.dll in the same directory as the .exe or into some directory in the PATH should be enough for your program to work.
If this works, you can then run ntldd without copying any DLLs beforehand, and copy only the necessary ones. The reason why you'd want to copy them at all at this point (since your app already works) is to be able to distribute it to others, without them having to install the compiler for its DLLs. Skip any DLLs located outside of your compiler's bin directory (except for SDL2.dll).
Note that the possibility of having weird DLLs in C:\Windows is real. E.g. Wine tends to put OpenAL32.dll into C:\Windows, so if you try this process with OpenAL on Wine, it will fail. If you're making a sciprt that runs ntldd automatically, prefer copying the DLLs (or at least symlinking them - I heard MSYS2 can emulate symlinks on Windows?).
Can I make an EXE that doesn't depend on any DLLs?
It's possible to make an .exe that doesn't depend on any (non-system) .dlls by using the -static linker flag, this is called "static linking". This is rarely done, and you shouldn't need to do this if you did the above steps correctly. This requires some additional linker flags; they are listed in file ??-w64-mingw32/lib/pkgconfig/sdl2.pc shipped with SDL, in the Libs.private section. Notice that there are two files, for x32 and x64 respectively.
How do I distribute my app to others?
Follow the steps in the previous section, titled procedure entry point ... could not be located in ....
A saner alternative?
There is MSYS2.
It has a package manager that lets you download prebuilt libraries, and, as a bonus, a fresh version of the compiler.
Install SDL2 from its package manager. Use a tool called pkg-config (also from the package manager) to automatically determine all necessary flags (pkg-config --cflags SDL2 for compiler flags, pkg-config --libs SDL2 for linker flags).
This is the same experience as you would have on Linux (maybe except for some DLL management hassle).
Bonus - Other problems
Q: My program always opens a console window when I run it, how do I hide it?
A: Add -mwindows to the linker flags.
Q: I get error 'SDL_VideoMode' wasn't declared in this scope.
A: SDL_VideoMode is from SDL1.2, it's not a part of the newer SDL2. Your code was written for the outdated version of SDL. Find a better tutorial that deals specifically with SDL2.
Q: My program has the default file icon, but I want a custom one.
A: Your icon must be in the .ico format. If your graphics editor doesn't support it, make a series of .pngs of common sizes (e.g. 16x16, 32x32, 48x48, 64x64), then convert them to a single .ico using ImageMagick: magick *.png result.ico (or with convert instead of magick).
Create a file with the .rc extension (say, icon.rc), with following contents MyIconName ICON "icon.ico" (where MyIconName is an arbitrary name, and "icon.ico" is the path to the icon). Convert the file to an .o using windres -O res -i icon.rc -o icon.o (the windres program is shipped with your compiler). Specify the resulting .o file when linking, e.g. g++ foo.cpp icon.o -o foo.exe.
Recent versions of SDL2 have a nice property of using the same icon as the window icon, so you don't have to use SDL_SetWindowIcon.
A solution for Visual Studio:
Why not use a package manager? I use vcpkg, and it makes super easy to consume 3rd party libraries. Grab the vcpkg source, and extract it to a safe place, like C:/, then run its bootstrap script bootstrap-vcpkg.bat, this will generate vcpkg executable. Then run vcpkg integrate install to make libraries installed with vcpkg available in Visual Studio.
Search for the library you need:
vcpkg search sdl
imgui[sdl2-binding] Make available SDL2 binding
libwebp[vwebp-sdl] Build the vwebp viewer tool.
magnum[sdl2application] Sdl2Application library
sdl1 1.2.15#12 Simple DirectMedia Layer is a cross-platform development library designed to p...
sdl1-net 1.2.8-3 Networking library for SDL
sdl2 2.0.12-1 Simple DirectMedia Layer is a cross-platform
...
Install it with: vcpkg install sdl2.
Now you just need include SDL2 headers, and everything will work out of the box. The library will be linked automatically.
You can learn more about vcpkg here.
On Mac this is what I follow for XCode (must install g++):
sdl linking:
g++ main.cpp -o main $(sdl2-config --cflags --libs)
XCODE project steps:
open terminal app (macOS)
BUILD SETTINGS (select 'all' and 'combined' search bar enter: "search")
click on "header search paths(way right side click)
add: /usr/local/include
BUILD PHASES --> LINK BINARY LIBRARIES (click plus)
type in SDL --> click "add other"
press: command+SHIFT+g (to bring search bar)
type in: usr/local/Cellar
navigate to: SDL2 -->2.0.8 -->lib --> libSDL2-2.2.0.dylib (make sure not shortcut)

Fail to find a function in yaml.h library (C)

I try to read a yml file in C (Code::Blocks IDE) but I receive an undefined reference error for yaml_parser_initialize:
#include <stdio.h>
#include <stdlib.h>
#include <yaml.h>
int main(){
FILE *fh = fopen("configuration.yaml", "r");
yaml_parser_t parser;
/* Initialize parser */
if(!yaml_parser_initialize(&parser))
fputs("Failed to initialize parser!\n", stderr);
fclose(fh);
return 0;}
The function exists in yaml.h. I linked the yaml library as follows:
Project->Build Options->Linker Settings: added src\.libs\libyaml.a
Project->Build Options->Search Directories->Compiler: added the include library: yaml-0.2.5\include.
Project->Build Options->Search Directories->Linker: added the include library: yaml-0.2.5\include.
OS: Win10
Thanks in advance.
In short, I will try to answer that and update my answer per request.
If you building on Linux OS, no matter if your host OS is Windows(you may run Linux as a virtual machine), you usually link with .a or .so library files.
If you build envinronment is Windows, no matter the host OS, then you usually link with .lib or .dll libraries.
That being said, the above mentioned OS'es have a different convention about how to supply a path to file.
On Linux the path go like this: /path/to/libs/libyaml.a.
On Windows the path go like this C:\Program Files\libs\yaml.lib.
Any app that runs on the OS follow the OS path convention. In your case Code::Blocks request you to supply a path in the convention the guest OS is.
The below text, is two methods of building your code with yaml library ob Ubuntu.
Update
I do not use Code::Blocks as of now. I've installed the IDE to check what your options are.
You talk about Ubuntu, C and yaml. That will be:
1) New Project->Console Application->C.
2) <Whichever project names you wish>
3) <Whatever compiler configuration you like>
That was to create a bunch of files that CB calls project. Now I dont know what sort of yaml library you use. But you talk about Ubuntu and C so...
1) apt search libyaml-><guess what yaml are>->apt install libyaml-dev
2) pkg-config --list-all | grep yaml gets me the output of yaml-0.1. That is the name I want to supply as argument to pkg-config.
BTW you seem to get a different version of yaml library. But still, all we need is to know proper strings to supply as compiler and linker arguments.
3) pkg-config --libs gets me -lyaml
4) pkg-config --cflags gets me empty line. So the include path is well-known for the build envinronment
This way, we know the linker arguments(-lyaml) and the compiler arguments(<empty string>). Now I try to insert them somewhere where CB could find them.
1) Menu options: Project->Build options...
2) Compiler settings-> no change
3) Linker settings->link libraries->yaml
The libraries in CB should go without -l prefix, so it should be as above. Hit build and all went OK.
Update for git version
It seems that your yaml version is newer than my distro version. If you need recent version, lets go and install that from git.
1) apt remove libyaml-dev. So that there will be no clashes with the library versions.
I did choose the Canonical repository for libyaml as my distro is Ubuntu. You need to mkdir for the sources and cd to that directory.
2) git clone https://github.com/yaml/libyaml
3) cd libyaml
4) Follow the instructions to build and install.
5) pkg-config --list-all | grep yaml gets me yaml-0.1
6) pkg-config --cflags yaml-0.1 produces -I/usr/local/include
7) pkg-config --libs yaml-0.1 gets this -L/usr/local/lib -lyaml
Ok we got the compiler & linker flags for the library. The link library option stays the same. You need to add -L/usr/local/lib to Other linker options. I did not find where I could add the compiler flags, so I'had added new flag. In CB that will be Compiler flags-><right mouse click>->New flag. Name the flag somehow and insert the -I/usr/local/include string to the Compiler flags input row. Hit OK button. Hit the checkbox in front of your newly created flag. Build & Run.

Running a 32-bit C code on a 64-bit system with Windows and a C compiler

I am trying to run a c code on my Windows laptop using the 64-bit MinGW compiler. There are a few lines in the beginning of the code that direct to other files such as:
#include <openssl/e_os2.h>
When compiling the code the following error shows up:
C:\MinGW\bin\openssl\apps>gcc s_server.c
s_server.c:21:27: fatal error: openssl/e_os2.h: No such file or directory
#include <openssl/e_os2.h>
^
compilation terminated.
I made sure the files were in the correct locations, however the error still occurs. I am thinking the error occurs because I am running a 32-bit binary on a 64-bit system. Are there any ways to work around this issue given that I don't have a Linux system?
C:\MinGW\bin\openssl\apps>gcc s_server.c
s_server.c:21:27: fatal error: openssl/e_os2.h: No such file or directory
#include <openssl/e_os2.h>
^
compilation terminated.
I believe you need a -I argument during compile. The headers are not located in the apps/ directory. Instead, they are located at ../include/ (relative to apps/).
So maybe a compile command like:
# from apps/ directory
gcc -I ../include/ s_server.c
You will probably have additional problems because you need to link against libssl and libcrypto. Be aware you will still have work to do.
Here is what it looks like on Linux:
openssl$ find . -name e_os2.h
./include/openssl/e_os2.h
openssl$ cd apps
apps$ ls ../include/openssl/e_os2.h
../include/openssl/e_os2.h
Since the relative path is ../include/openssl/e_os2.h and the source file #include "openssl/e_os2.h", you only need to include ../include using -I.
I am running a 32-bit binary on a 64-bit system...
You need to build OpenSSL as 32-bit. Run ./Configure LIST to get a list of MinGW targets. Then, configure with the appropriate triplet.
You may need to add -m32 to the command line for your program.

Compiling a Linux program under Mac OS X

I am trying to use make under Mac OS X (El Capitan) to compile a program which I know to work under Linux. The program makes use of USB libraries. I had to modify the config.mk file for these libraries to be found, but now I end up with errors in the compilation (undeclared identifiers).
Link to source: https://github.com/pali/0xFFFF
It requires usb.h, which seems to be part of usblib-compat. I installed the latter by brew install usblib-compat. But still usb.h couldn't be seen, although I knew where it was: specifically, symbolic link to usb.h and to the library may be found under /usr/local/include and under /usr/local/lib, respectively.
After many trials, I progressed somehow. Namely, the file config.mk is clearly read during the make'ing process, although I have to admit that it is not clear to me how this is done; anyway, I noticed two lines commented:
CPPFLAGS += -I/usr/local/include
LDFLAGS += -L/usr/local/lib -Wl,-R/usr/local/lib
(for the sake of precision, in the original config.mk the local dir was replaced by a pkg dir. I replaced it in these lines.)
I uncommented them and now something happens: the usb.h is found. I think the first of these variable definitions tells the compiler where to look tor header files, and the second tells the linker where to look for libraries - but again it is not completely clear to me.
In any case, I have still problems. Namely, the make'ing process outputs two warnings and an error, and then stops:
usb-device.c:90:57: warning: unused parameter 'udev' [-Wunused-parameter]
static void usb_reattach_kernel_driver(usb_dev_handle * udev, int interface) {
^
usb-device.c:90:67: warning: unused parameter 'interface' [-Wunused-parameter]
static void usb_reattach_kernel_driver(usb_dev_handle * udev, int interface) {
usb-device.c:324:13: error: use of undeclared identifier 'RTLD_DEFAULT' if ( dlsym(RTLD_DEFAULT, "libusb_init") )
Seems this program is difficult to port from Linux to Mac, although I think it should be portable. If anyone has any idea about what to do (apart from running a Linux distribution...), it would be much appreciated.
EDIT
dlfcn.h has the following:
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define RTLD_NOLOAD 0x10
#define RTLD_NODELETE 0x80
#define RTLD_FIRST 0x100 /* Mac OS X 10.5 and later */
/*
* Special handle arguments for dlsym().
*/
#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */
#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */
#define RTLD_SELF ((void *) -3) /* Search this and subsequent objects (Mac OS X 10.5 and later) */
#endif /* not POSIX */
Ok, finally I have been successful. I think it be worth publishing my solution - maybe others could find it useful.
So, the first point is: if I run make in the program's main folder, usb.h is not found. Then, we have to install the corresponding library.
There are two possibilities for this to be done. The first and more obvious would be to install, through home brew, libusb-1.0 and libusb-compat (the latter provides a compatibility interface for programs that use libusb-0.1, which is the first version of libusb, and is not compatible with libusb-1.0. usb.h is included in libusb-compat):
brew install libusb
brew install libusb-compat
However, this leads to other problems, as reported in the other answer. I had worked around them, but eventually found out that my program got angry when using libusb-compat (if I understand correctly, interfacing the usb port through two layers of libraries is too slow for a flasher).
So, the other possibility: installing the actual libusb-0.1. This is not available through home brew. It is however available through ports, with the name of libusb-legacy. So, I had to install ports, install the X-code command line utilities (which required first going to Apples' website to accept their legal things...) and run
sudo port install libusb-legacy
Ok, now calling make would not do the trick since the compiler is not able to find the library yet. For that, I had to edit the config.mk file which is included in the main directory of the program, uncommenting the last two lines, and editing them somewhat in order to point to the directory where libusb-legacy is stored:
CPPFLAGS += -I/opt/local/include/libusb-legacy -D_DARWIN_C_SOURCE
LDFLAGS += -L/opt/local/lib/libusb-legacy
(the -D_DARWIN_C_SOURCE defines the environmental variable required for other variables to be defined by the libraries. In the Makefile in the src directory, in fact, _POSIX_C_SOURCE is defined.)
Do you think all this did the job? No. In fact at this point I ended up with another error: the linker not being able to find some library called -lusb. I don't know why this syntax, but after some thought I realised that -lusb is somewhat a short for libusb. And the libusb I am using is actually called libusb-legacy... So I went into the Makefile in the src directory, where -lusb is introduced, and changed -lusb to -lusb-compat. Tah-dah! Compiled. A few warnings about non-used variables and a comparison between two different types of integers, but nothing more. And the program runs - after a few trials, I have been able to reflash my bricked phone, which now is alive again! Very happy!!! :)
Looking at the dlfcn.h source code, it seems that the identifier is defined only if _POSIX_C_SOURCE is not defined, or _DARWIN_C_SOURCE is defined. Thus I'd just add #define _DARWIN_C_SOURCE;
Or you could add the corresponding -D switch in the config.mk:
CPPFLAGS += -I/usr/local/include -D_DARWIN_C_SOURCE

Installing a new library in Linux, and accessing it from my C code

I am working on a project which requires me to download and use this. Inside the downloaded folder, when extracted I am presented with three things:
A folder called "include"
A folder called "src"
A file called "Makefile"
After some research, I found out that I have to navigate to the directory which contains these files, and just type in the command make.
It seemed to install the library in my system. So I tried a sample bit of code which should use the library:
csp_conn_t * conn;
csp_packet_t * packet;
csp_socket_t * socket = csp_socket(0);
csp_bind(socket, PORT_4);
csp_listen(socket, MAX_CONNS_IN_Q);
while(1) {
conn = csp_accept(socket, TIMEOUT_MAX);
packet = csp_read(conn, TIMEOUT_NONE);
printf(“%S\r\n”, packet->data);
csp_buffer_free(packet);
csp_close(conn);
}
That's all that was given for the sample server end of the code. So I decided to add these to the top:
#include <csp.h>
#include <csp_buffer.h>
#include <csp_config.h>
#include <csp_endian.h>
#include <csp_interface.h>
#include <csp_platorm.h>
Thinking I was on the right track, I tried to compile the code with gcc, but I was given this error:
csptest_server.c:1: fatal error: csp.h: No such file or directory
compilation terminated.
I thought I may not have installed the library correctly after all, but to make sure, I found out I could check by running this command, and getting this result:
find /usr -iname csp.h
/usr/src/linux-headers-2.6.35-28-generic/include/config/snd/sb16/csp.h
/usr/src/linux-headers-2.6.35-22-generic/include/config/snd/sb16/csp.h
So it seems like the csp.h is installed, maybe I am referencing it incorrectly in the header include line? Any insight? Thanks a lot.
The make command is probably only building the library, but not installing it. You could try sudo make install. This is the "common" method, but I recommend you to check the library's documentation, if any.
The sudo command is only necessary if you have no permissions to write the system's include and library directories, which may be your case.
Another possibility (instead of installing the library) is telling GCC the location of the library's source code and generated binaries (by means of the -I and -L options of the gcc command.
That Makefile will not install anything, just translate the source into a binary format.
The csp.h in the Linux kernel has nothing to do with your project, it's just a naming collision, likely to happen with three letter names.
In your case, I would presume you need to add the include directory to the compilation flags for your server, like gcc -I/path/to/csp/include/csp csptest_server.c.
(Next, you'll run into linker errors because you'll also want to specify -L/path/to/csp -lcsp so that the linker can find the binary code to link to.)

Resources