I copied the example code in the Haskell FFI guide as a first step to exporting my Haskell program as a C library, but can't get it to compile. I have foo.hs:
module Foo where
foreign export ccall foo :: Int -> IO Int
foo :: Int -> IO Int
foo n = return (length (f n))
f :: Int -> [Int]
f 0 = []
f n = n:(f (n-1))
This successfuly compiled to foo_stub.h and foo_stub.o. Here's foo_stub.h:
#include "HsFFI.h"
#ifdef __cplusplus
extern "C" {
#endif
extern HsInt foo(HsInt a1);
#ifdef __cplusplus
}
#endif
But then my C program didn't compile:
#include "foo_stub.h"
main() { foo(1); } // I realize this is probably wrong, and would also like advice on doing this part correctly, but note the error is not here.
error:
gcc foo.c
In file included from foo.c:1:0:
foo_stub.h:1:19: fatal error: HsFFI.h: No such file or directory
#include "HsFFI.h"
^
compilation terminated.
I assume I'm missing some header files or haven't pointed gcc to them correctly. I can provide more information if necessary. Any ideas on how to fix this?
I found "HsFFI.h" at /usr/local/lib/ghc-7.10.2/include/HsFFI.h. You should be able to direct GCC to look there with the -I option. More information here.
Related
I'm new to C and programming.
I'm on Windows 10, I just installed Dev-C++ and I'm learning how to call functions from other files: i wrote this function to sum two numbers, and I call it from the main script.
The problem is that when i compile the func.c file I get the error in title, so if I run the main file it doesn't recognize the "sum" function.
This is the main.c file:
#include <stdio.h>
#include "func.h"
main(){
int x,y,s;
scanf("%d %d",&x,&y);
s = sum(x,y);
printf("\n%d",s);
}
This is the header file:
#ifndef FUNC_H_INCLUDED
#define FUNC_H_INCLUDED
int func(int a, int b);
#endif // FUNC_H_INCLUDED
And this is the code of the sum function in a func.c file:
#include <stdio.h>
#include "func.h"
int func(int a, int b){
return(a+b);
}
I did read lots of other questions, but they didnt help in my case, or I didnt get the tricky answer.
Thank you.
In case you are using Embarcadero's Dev-C++. I use their free compiler since it is "portable".
func.c and func.h both contain a function called func while your main file has a function called sum, you must have a consistency in the names, you can do s=func(x,y) and that should work, but a good practice is doing the opposite and replace func in other files by sum.
And you must compile the 3 files, compiling 1 or 2 isn't enough.
To compile them using Embarcadero's free compiler:
C:\path\to\compiler\bcc32x func.c func.h main.c
It will give you main.exe that you can run from the command prompt.
I want to access to member in struct but check if this member exist
#include <stdio.h>
int main()
{
struct MyStruct { int a;};
struct MyStruct temp ;
temp.a=3;
return 0;
}
Is there a way to check if member a is in struct m and if not access to b with #ifdef ?
something like #ifdef MyStruct.a temp.a=3; #else temp.b=3; #endif
It's not possible to do in C.
The usual way if you really want to detect a member of a struct, is to first compile a sample program that uses the struct, see if the compilation succeeds and depending on the result define or not a preprocessor macro to the compiler used to compile the rest of the project. Various build systems were created to ease up such tasks. A short example with cmake may look like the following:
cat >mystruct.h <<EOF
struct MyStruct {
int a; // a? maybe not? no one knows.
};
EOF
cat >CMakeLists.txt <<EOF
cmake_minimum_required(VERSION 3.11)
project(test_include C)
# will try to compile a testing file
try_compile(mystruct_has_a "${CMAKE_BINARY_DIR}/temp" ${CMAKE_SOURCE_DIR}/test_mystruct_has_a.c)
add_executable(main main.c)
if(mystruct_has_a)
target_compile_definitions(main PUBLIC MYSTRUCT_HAS_A)
endif()
EOF
cat >test_mystruct_has_a.c <<EOF
#include "mystruct.h"
int main() {
struct MyStruct temp;
temp.a = 3; // test - can we compile this?
}
EOF
cat >main.c <<EOF
#include <stdio.h>
#include "mystruct.h"
int main() {
struct MyStruct temp ;
#if MYSTRUCT_HAS_A
// it's ok to use `temp.a` here.
temp.a = 3;
printf("%d\n", temp.a);
#endif
}
EOF
Which can be compiled with from the command line:
cmake -S. -B_build && cmake --build _build --verbose
cmake will try to compile file test_mystruct_has_a.c. If the compilation is successful, then the macro MYSTRUCT_HAS_A will be added as a macro to compiler arguments. If not, the macro will not be added. Then main.c will compile with that macro or without depending on the previous result. Such a way is typically used in many, many various projects mostly to provide portability by detecting operating system specific stuff, from top of my head for example members of sigaction, siginfo_t or sched_param.
I get the following errors when I'm trying to build my c code files with -D. But, if I build it without -D, it works. I don't know why. Thanks. (My machine is ubuntu12.10, 32bit)
gcc c1.c c2.c -D DEBUG
/tmp/ccX04EIf.o:(.data+0x0): multiple definition of `g'
/tmp/cc0j9MoU.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status
Here is my source code:
global.h
#ifdef DEBUG
int g = 23;
static int init = 1;
#else
int g;
static int init = 0;
#endif
c1.c
#include "global.h"
int f() {
return g + 1;
}
c2.c
#include <stdio.h>
#include "global.h"
int main() {
if (!init) {
g = 37;
}
int t = f();
printf("calling f yields %d\n", t);
return 0;
}
You define the variable g in the header file, that means it will be defined in all source files that includes the header file.
Instead declare it, like
extern int g;
and then define it in a single source file.
The difference between the two code paths (with and without DEBUG) is the initialization of the g variable. Without it, it is only a "tentative" definition, and so the symbol is only generated in the file that really uses it, namely c2.o.
With initialization it is a real definition of the symbol, and so it is also generated in c1.o.
As a rule of thumb, header files should never contain data definitions, only declarations. Data "declarations-only" should be made with the keyword extern. You'd then need to define any such symbol in exactly one of your .c files.
I'm trying to embed LuaJIT into a C application. The code is like this:
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <stdlib.h>
#include <stdio.h>
int barfunc(int foo)
{
/* a dummy function to test with FFI */
return foo + 1;
}
int
main(void)
{
int status, result;
lua_State *L;
L = luaL_newstate();
luaL_openlibs(L);
/* Load the file containing the script we are going to run */
status = luaL_loadfile(L, "hello.lua");
if (status) {
fprintf(stderr, "Couldn't load file: %s\n", lua_tostring(L, -1));
exit(1);
}
/* Ask Lua to run our little script */
result = lua_pcall(L, 0, LUA_MULTRET, 0);
if (result) {
fprintf(stderr, "Failed to run script: %s\n", lua_tostring(L, -1));
exit(1);
}
lua_close(L); /* Cya, Lua */
return 0;
}
the Lua code is like this:
-- Test FFI
local ffi = require("ffi")
ffi.cdef[[
int barfunc(int foo);
]]
local barreturn = ffi.C.barfunc(253)
io.write(barreturn)
io.write('\n')
It reports error like this:
Failed to run script: hello.lua:6: cannot resolve symbol 'barfunc'.
I've searched around and found that there're really little document on the ffi module. Thanks a lot.
ffi library requires luajit, so you must run lua code with luajit.
From the doc:
"The FFI library is tightly integrated into LuaJIT (it's not available as a separate module)".
How to embed luajit?
Look here http://luajit.org/install.html under "Embedding LuaJIT"
Under mingw your example run if i add
__declspec(dllexport) int barfunc(int foo)
at the barfunc function.
Under Windows luajit is linked as a dll.
As misianne pointed out, you need to export the function, which you can do by using extern if you are using GCC:
extern "C" int barfunc(int foo)
{
/* a dummy function to test with FFI */
return foo + 1;
}
If you are experiencing problems with undefined symbols under Linux using GCC, take care to have the linker add all symbols to the dynamic symbol table, by passing the -rdynamic flag to GCC:
g++ -o application soure.cpp -rdynamic -I... -L... -llua
For those of you trying to make this work on Windows with VC++ (2012 or later), using the C++ compiler:
make sure you use the .cpp extension, as this will do C++ compilation
make the function have external C linkage so that ffi can link to it, with extern "C" { ... }
export the function from the executable, with __declspec(dllexport)
optionally specify the calling convention __cdecl, not required because should be it by default and not portable
wrap the Lua headers in an extern "C" { include headers }, or better just #include "lua.hpp"
#include "lua.hpp"
extern "C" {
__declspec(dllexport) int __cdecl barfunc(int foo) {
return foo + 1;
}}
I'm doing some test to learn how to create shared library.
The template for shared libraries in Code::Blocks is this
library.c
// The functions contained in this file are pretty dummy
// and are included only as a placeholder. Nevertheless,
// they *will* get included in the shared library if you
// don't remove them :)
//
// Obviously, you 'll have to write yourself the super-duper
// functions to include in the resulting library...
// Also, it's not necessary to write every function in this file.
// Feel free to add more files in this project. They will be
// included in the resulting library.
// A function adding two integers and returning the result
int SampleAddInt(int i1, int i2)
{
return i1 + i2;
}
// A function doing nothing ;)
void SampleFunction1()
{
// insert code here
}
// A function always returning zero
int SampleFunction2()
{
// insert code here
return 0;
}
I tried to compile it, and it compiled without any error or warning. But when i tried to use it with the ctyped.cdll.LoadLibrary("library path.dll") in python 3(that actually should work like the C function), it said that it wasn't a valid win32 application. Both python and code::blocks are 32 bit (code:blocks compile with gcc, and i tryed to use an installed version of mingw on my system, but it gives some error about a missing library) while i'm working on win 7 64bit
Do you know what the problem can be, or if i'm doing something wrong?
EDIT1:
i'm on windows 7 64bit, in the specs file of the compiler is wrote: "Thread model: win32, gcc version 3.4.5 (mingw-vista special r3)"
and i used as command
gcc.exe -shared -o library.dll library.c
in python i used
from ctypes import *
lib = cdll.LoadLibrary("C:\\Users\\Francesco\\Desktop\\C programmi\\Python\\Ctypes DLL\\library.dll")
and the error was
WindowsError: [Error 193] %1 is not a valid Win32 application
i installed both python3.1 and mingw from the binary package and not compiling them on my system
EDIT2:
After reading Marc answer.
main.h
#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C"
{
#endif
DLL_EXPORT int MySimpleSum(int A, int B);
#ifdef __cplusplus
}
#endif
#endif // __MAIN_H__
main.c
#include "main.h"
// a sample exported function
DLL_EXPORT int MySimpleSum(int A, int B)
{
return A+B;
}
compiling options
gcc -c _DBUILD_DLL main.c
gcc -shared -o library.dll main.o -Wl,--out-implib,liblibrary.a
with gcc 4.5.2
still get the same error..
I believe in the windows environment you need to use the __declspec annotation. How to create a shared library and the use of __declspec is described here: DLL Creation in MingW.