Trying to export a Haskell lib for C - c

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

'Undefined reference to `WinMain' ' error on minimal script, Dev-C++

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.

Check is member in struct with C

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.

Error when building c code with -D

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.

How to use LuaJIT's ffi module when embedding?

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;
}}

Create a valid shared library in C

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.

Resources