Dart C Interoperability. Pass an array of integers to C function - c

I am learning Dart now and I playing with Dart's Interoperability with C. I am able to use a C method with two int params. Code below:
hello.dart
import 'dart:ffi' as ffi;
typedef sum_func = ffi.Int32 Function(ffi.Int32 a, ffi.Int32 b);
typedef Sum = int Function(int a, int b);
...
final dylib = ffi.DynamicLibrary.open(path);
final sumPointer = dylib.lookup<ffi.NativeFunction<sum_func>>('sum');
final sum = sumPointer.asFunction<Sum>();
print('3 + 5 = ${sum(3, 5)}');
hello.c
int sum(int a, int b){
return a + b;
}
hello.h
int add(int x, int y)
hello.def
LIBRARY hello
EXPORTS
sum
This all works really well, but I also want to have an max C method, which takes an int array as an input and returns the biggest number. How can I do this? I've implemented all the required code in C, but I am not sure how do I "link" it with Dart. Could anyone help me please?

First, I really want to say that I am not a C programmer and especially when it comes to pointers I am not even pretending I have a fully understanding of how to do this kind of things the most optimal way.
With this out of the way here is my solution based on the primitives example found here: https://github.com/dart-lang/samples/tree/master/ffi/primitives
primitives.dart
import 'dart:ffi';
import 'dart:io' show Platform;
import 'package:ffi/ffi.dart';
typedef max_func = Int32 Function(Pointer<Int32> list, Int32 size);
typedef Max = int Function(Pointer<Int32> list, int size);
void main() {
var path = './primitives_library/libprimitives.so';
if (Platform.isMacOS) path = './primitives_library/libprimtives.dylib';
if (Platform.isWindows) path = r'primitives_library\Debug\primitives.dll';
final dylib = DynamicLibrary.open(path);
final list = [1, 5, 3, 59030, 131000, 0];
final listPtr = intListToArray(list);
final maxPointer = dylib.lookup<NativeFunction<max_func>>('max');
final max = maxPointer.asFunction<Max>();
print('${max(listPtr, list.length)}'); // 131000
malloc.free(listPtr);
}
Pointer<Int32> intListToArray(List<int> list) {
final ptr = malloc.allocate<Int32>(sizeOf<Int32>() * list.length);
for (var i = 0; i < list.length; i++) {
ptr.elementAt(i).value = list[i];
}
return ptr;
}
primitives.h
int max(int *listPtr, int size);
primitives.c
#include "primitives.h"
int max(int *listPtr, int size)
{
int currentMax = *listPtr;
for (int i = 0; i < size; i++)
{
if (currentMax < *listPtr)
{
currentMax = *listPtr;
}
listPtr++;
}
return currentMax;
}

Related

how to copy go slice into c pointer

I need to pass slice of structure objects to C function. C function expects pointer to struct objects
I followed How to pass pointer to slice to C function in go.
I tried to replicate the original requirement in sample. In sample I am getting
could not determine kind of name for C.f
I am C programmer, just started working on Go-module of project. Can someone correct the below sample or provide a sample to pass go slice to C-function (C-code takes pointer to structure or double pointer (whatever is appropriate))
here is my sample code
package main
/*
#include <stdio.h>
#include "cgoarray.h"
struct test {
int a;
int b;
};
int f(int c, struct test **s) {
int i;
printf("%d\n", c);
for (i = 0; i < c; i++) {
printf("%d\n", s[i].a);
}
c = (c) + 1;
return 1;
}
*/
import "C"
import "unsafe"
type struct gotest{
a int
b int
}
func go_f(harray ...gotest) {
count := len(harray)
c_count := C.int(count)
cArray :=(*C.struct_test)(C.malloc(C.size_t(c_count) *8));
// convert the C array to a Go Array so we can index it
a := (*[1<<30 - 1]*C.struct_test)(cArray)
for index, value := range harray {
a[index] = value
}
err := C.f(10, (**C.struct_test)(unsafe.Pointer(&cArray)))
return 0
}
func main(){
t :=gotest{10,20}
t1 :=gotest{30,40}
t2 :=gotest{50,60}
fmt.Println(t,t1,t2)
go_f(t1,t2,t3)
}
Run this main.go:
package main
/*
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int a;
int b;
} Foo;
void pass_array(Foo **in, int len) {
for(int i = 0; i < len; i++) {
printf("A: %d\tB: %d\n", (*in+i)->a, (*in+i)->b);
}
}
*/
import "C"
import (
"unsafe"
)
type Foo struct{ a, b int32 }
func main() {
foos := []*Foo{{1, 2}, {3, 4}}
C.pass_array((**C.Foo)(unsafe.Pointer(&foos[0])), C.int(len(foos)))
}
With:
GODEBUG=cgocheck=0 go run main.go

Array of functions with built in arguments in C

Say I have these two functions and a definition of an array of these two functions:
int flag;
int add(int a, int b){
return a+b;
}
int multiply(int a, int b){
return a*b;
}
typedef int(*f)(int, int);
f func_array[2] = {&add, &multiply};
Now, there is a specific place in my code that I want to call these two functions depending on my flag state with the same arguments each time.
For example:
int var;
if(flag == 0)
{
var = func_array[flag](1,1);
}
else{
var = func_array[flag](2,2);
}
Is there a way to define it inside the array itself? Somwhow defining the array like this and just call the function:
f func_array[2] = {&add(1,1), &multiply(2,2)};
int var = func_array[flag]();
Is this a valid way? Is there any more elegant way to do it?
You can define a set of arrays for each parameter:
#define ARR_SIZE 2
typedef int(*f)(int, int);
f func_array[ARR_SIZE] = {&add, &multiply};
int param1_array[ARR_SIZE] = { 1, 2};
int param2_array[ARR_SIZE] = { 1, 2};
The call would become
if(flag < ARR_SIZE)
{
int var = func_array[flag](param1_array[flag], param2_array[flag]);
}
I just added a check on the array size.
With a macro
#define flag_call(flag) \
func_array[flag](param1_array[flag], param2_array[flag])
you could simplify it even more
if(flag < ARR_SIZE)
{
flag_call(flag);
}
Not sure what the point is but you can do this:
int add11(void){ return add(1,1); }
int multiply22(void){ return multiply(2,2); }
/*skipped the new typedef*/
int (*func_array2[2])(void) = {&add11,&multiply22};
https://godbolt.org/z/ejMn4n
The wrappers could even be inlinable if you make the array static or auto.
You can use a struct to bundle them together:
typedef int(*f)(int, int);
struct func_and_args {
f func;
int a;
int b;
}
...
struct func_and_args arr[] = {{&add,1,1},{&multiply,2,2}};
int var = arr[flag].func(arr[flag].a,arr[flag].b);

How to pass a comparator to a C function?

What is bool (*comparator)(void *, void *)?
I'm trying to use this function from a library, but I don't understand its signature.
The function seems to be expecting some kind of criteria to sort the list (as ASC or DESC in SQL, I think), as a higher order function.
void list_sort(t_list *self, bool (*comparator)(void *, void *)) {
int unsorted_elements = self->elements_count;
if(unsorted_elements < 2) {
return;
}
t_link_element *aux = NULL;
bool sorted = true;
do {
t_link_element *previous_element = self->head, *cursor = previous_element->next;
sorted = true;
int index = 0, last_changed = unsorted_elements;
while(index < unsorted_elements && cursor != NULL) {
if(!comparator(previous_element->data, cursor->data)) {
aux = cursor->data;
cursor->data = previous_element->data;
previous_element->data = aux;
last_changed = index;
sorted = false;
}
previous_element = cursor;
cursor = cursor->next;
index++;
}
unsorted_elements = last_changed;
} while(!sorted);
}
The last definition of the function was in commons/collections/list.h.
I can't figure how to use this function properly after many attempts.
#include <stdio.h>
#include <stdlib.h>
#include <commons/collections/list.h>
/*I added this function thanks to the help of the community,
*and now it works, the list is printed backwards now.*/
bool comparator(void * a, void * b) {
return (int*) a > (int*) b;
}
int main()
{
t_list *list = list_create();
int add[] = {4, 55, 9, 7, 17};
list_add(list, (void*) &add[0]);
list_add(list, (void*) &add[1]);
list_add(list, (void*) &add[2]);
list_add(list, (void*) &add[3]);
list_add(list, (void*) &add[4]);
int size = list_size(list);
int j = 0 ;
while( j++ < 2)
{
for ( int i = 0 ; i < size; i++)
{
int* element = (int*) list_get(list, i);
printf("Found %d\n", *element);
}
//I edited this line, now the second parameter is comparator
list_sort(list, comparator);
}
list_destroy(list);
}
The main() function prints
Found 4 Found 55 Found 9 Found 7 Found 17
Found 17 Found 7 Found 9 Found 55 Found 4
EDIT:
I created the function comparator that actually allows me to run the code
After printing the result I showed before, it prints the same list but backwards.
Thanks everyone who's been nice and helped me fixed this, I still don't know how to print the sorted list. Sorry if my question is useless and/or violates some guideline, I wouldn't ask it this way if I knew it did.
Looking at the code in your last edit, the function is plain wrong. (int*) a > (int*) b compares pointer addresses, not values. If you intend to return true if a is greater than b, then it should be:
bool is_greater (void * a, void * b) {
return *(int*) a > *(int*) b;
}
More readably written as:
bool is_greater (void* a, void* b)
{
const int* ia = a;
const int* ib = b;
return *ia > *ib;
}
The function pointer type used by that API has some code smell, the parameters should have been declared as const void* so that the code can be used on read-only data too, but I guess you can't change that part.
In C++ we would have a predicate - an operator which returns true if the lhs < rhs
So your C function looks like it is following that pattern.
bool myLessInt(void * lhs, void * rhs)
{
// assume input parameters lhs and rhs are pointers into the data.
int intLhs = *((int*)lhs);
int intRhs = *((int*)rhs);
if( intLhs < intRhs ) return true; // lhs was less than rhs
return false; // rhs == or is less than lhs
}
I would look for a function like the one above to solve your problem.

why pass as argument of a function a function?

i have a little question.
i'm studying C with devc++ (as start) and i have seen as argument function you can pass a function, this is ok but why?
for example u can write as argument:
void myfunc(void(*func)(int)){}
but if u simple call function with his name and argument it is not better?
like example:
void myfunction (){name of func to call(myargs); }
there's a difference?
it seems the same thing but with more simple and short code
edit:
i want only know
void map (int (*fun) (int),int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = fun(x[i]);
}
why u use this instead of:
void map (int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = nameoffunction(yourargument);
}
You can use a function pointer as a parameter if you want your function to do different things depending on what the user wants.
Here's a simple example:
#include <stdio.h>
int add(int x, int y)
{
return x + y;
}
int subtract(int x, int y)
{
return x - y;
}
int multiply(int x, int y)
{
return x * y;
}
int divide(int x, int y)
{
return x / y;
}
int operation(int x, int y, int (*func)(int, int))
{
printf(" x=%d, y=%d\n", x, y);
return func(x,y);
}
int main()
{
int x = 8, y = 4;
printf("x+y=%d\n", operation(x,y,add));
printf("x-y=%d\n", operation(x,y,subtract));
printf("x*y=%d\n", operation(x,y,multiply));
printf("x/y=%d\n", operation(x,y,divide));
return 0;
}
A very good example is the classic sorting function qsort. It's a library function, which means that you only have access to it's prototype. In order to make qsort general, you have to write your own compare function. A typical implementation looks like this for regular integers:
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
And then, if you have an array arr of integers you can sort it with qsort(arr, sizeof(arr), cmpfunc)
You might ask why this is not built in the qsort function? After all, it would be easy to make it work for both floats and integers. Yes, but imagine if you have an array of structs that look like this:
struct {
char *firstname;
char *lastname;
int age;
} persons[10];
How would you sort this? Well, that's not obvious. You might want all three. In that case, write three different compare functions.
i want only know
void map (int (*fun) (int),int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = fun(x[i]);
}
why u use this instead of:
void map (int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = nameoffunction(yourargument);
}
Let's answer the question with a question - what if you want to perform more than one type of mapping? What if you want to map both x2 and √x?
You could certainly do something like
void map( int x[], int l, int type )
{
for ( int i = 0; i < l; i++ )
{
if ( type == MAP_SQUARED )
x[i] = int_square( x );
else if ( type == MAP_ROOT )
x[i] = int_root( x );
...
}
}
which works, but is hard to read and cumbersome to maintain - every time you want to perform a new mapping, you have to add a new case to the map function.
Compare that to
void map( int x[], int l, int (*fun)(int) )
{
for ( int i = 0; i < l; i++ )
x[i] = fun( x[i] );
}
...
map( x, l, int_square );
map( y, l, int_root );
You don't have to hack the map function to get different mappings - you only have to pass the function that operates on the individual elements. If you want to perform a new mapping, all you have to do is write a new function - you don't have to edit the map function at all.
The C standard library uses this form of delegation in several places, including the qsort function (allowing you to sort arrays of any type in any order) and the signal function (allowing you to change how a program reacts to interrupts dynamically).

QuickSort in C library

The Second Param of qsort
Now I want to sort a set of points by x.Following is my code:
typedef struct {
int x;
int y;
} point;
int cmpfunc( const void * a, const void * b){
point *point1 = (point *)(a);
point *point2 = (point *)(b);
if(point1->x < point2->x){
return -1;
}
return 0;
}
int main(){
point *points = (point *)malloc(sizeof(point)*3);
points[0].x = 1;
points[0].y = 2;
points[1].x = 0;
points[1].y = 4;
points[2].x = 4;
points[2].y = 3;
qsort(points,2,(sizeof(points[0])),cmpfunc);
int i=0;
while (i<3){
printf("x=%d",points[i].x);
printf("y=%d\n",points[i].y);
i++;
}
return 0;
}
Please notice qsort(points,2,(sizeof(points[0])),cmpfunc);
The result is correct when I pass the second param value 2 not 3.What's wrong with my code?
To sort on the x axis, you need something like:
static void cmpfunc(const void *a, const void *b)
{
const point *pa = a, *pb = b;
return pa->x < pb->x ? -1 : pa->x > pb->x;
}
It must return less than, equal to, or greater than zero. See the manual page for more.
Oh, and you really shouldn't "drop const" like that, for no reason, and of course you never need to cast from void * to a pointer to struct like we have here. Keep it simple, and learn these things so you don't feel a need to "throw in a cast for good measure".

Resources