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
Related
I have created a struct in C with three members of type int.
I want to use a function to compute the value of the member C by adding the values a and b as shown in my code.
#include <stdio.h>
typedef struct nums
{
int a;
int b;
int c;
} number;
void add (number one);
int main (void)
{
number start = {.c = 3, .b = 4};
add (start);
printf("the sum is %d \n", start.c);
return (0);
}
void add (number one)
{
one.c = one.a + one.b;
}
When I run the code, I get the value of c as 3 instead of 7. How can I solve this problem?
Pass argument as a pointer
#include <stdio.h>
typedef struct nums
{
int a;
int b;
int c;
} number;
void add (number *pOne);
int main (void)
{
number start = {.a = 3, .b = 4, .c = 0};
add (&start);
printf("the sum is %d \n", start.c);
return (0);
}
void add (number *pOne)
{
pOne->c = pOne->a + pOne->b;
}
WHY POINTERS?
You pass the address of start as a pointer to add so that you can update start from within add(...). Otherwise, add would update a copy of start stored on the stack that gets popped off on the return of add.
Basically in C, if you pass a variable to a function, first the value of the variable is copied and then the function receives it.
So add function modifies the copy, not original one.
If you want to modify the original one in another function, you should pass the address of a variable.
Addresses are also copied when passed, but it's not a problem because the destination isn't copied.
#include <stdio.h>
typedef struct tagNumber {
int a;
int b;
int c;
} Number;
void add(Number* one) {
one->c = one->a + one->b;
}
int main() {
Number start = { .c=3, .b=4 };
add(&start);
printf("the sum is %d\n", start.c);
return 0;
}
I am trying to create two functions and put them outside the main{ }.
The question requires the user to enter a number that should be end_size > start_size > 9.
And if not just prompt it again.
I have two questions.
Here is the first problem, in function int get_start_size, the function should be stored the value in int start_size. Then, why I cannot call it from another function int get_end_size?
#include <cs50.h>
#include <stdio.h>
int get_start_size(void);
int get_end_size(void);
int main(void)
{
int i = get_start_size();
printf("%i\n", i);
int j = get_end_size();
printf("%i\n", j);
}
int get_start_size(void)
{
int start_size;
do
{
start_size = get_int("Start size is:");
}
while (start_size < 9);
return start_size;
}
int get_end_size(void)
{
int end_size;
do
{
end_size = get_int("End size is:");
}
while (end_size < start_size); //<<<<<<<<<<<<<this is the alert I got, use of undeclared identifier 'start_size'.
return end_size;
}
And the second problem is if I change it like this:
int get_end_size(void)
{
int end_size;
int k = get_start_size(); //<<<<<<<<<<<<< Should I call function like this?
do
{
end_size = get_int("End size is:");
}
while (end_size < k); //this is the problem I got, how to use value "int s" from other function "int get_start_size(void)"?
return end_size;
}
The result will be like this:
~/lab/ $ ./population
Start size is:10
10
Start size is:10 //duplicated prompt
End size is:22
22
~/lab/ $
The result quite meet my goal, but I think I called the function in the wrong way because it asks the user to enter two times the start size. How should I do it instead? Thanks.
Local Variables
Variables that are declared inside a function or block are called
local variables. They can be used only by statements that are inside
that function or block of code. Local variables are not known to
functions outside their own.
start_size is not visible inside get_end_size(), to make it visible, pass the value as a parameter to the function:
The prototype should be:
int get_end_size(int start_size);
For your second snippet, I understand that you want to return 2 values from the function, you can achieve that using a struct:
struct size
{
int start, end;
};
struct size get_size(void)
{
struct size size = {0, 0};
size.start = get_start_size();
do
{
size.end = get_int("End size is:");
}
while (size.end < size.start);
return size;
}
Or you can use pointers:
void get_size(int *start, int *end)
{
*start = get_start_size();
do
{
*end = get_int("End size is:");
}
while (*end < *start);
}
call it from main using:
int start, end;
get_size(&start, &end);
Or you can pass an array:
enum {START, END};
void get_size(int size[])
{
size[START] = get_start_size();
do
{
size[END] = get_int("End size is:");
}
while (size[END] < size[START]);
}
In this case, main should look like:
int size[2];
get_size(size);
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);
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;
}
So I am now rewriting my fortran code in C (to use CUDA), and apparently I do not understand how to properly use malloc and pointers. I am trying to make the main function just calls to other functions, which need to malloc arrays that will then be used inside other functions. So, I am passing pointers of pointers to them as per this post: C Programming: malloc() inside another function
But the right amount of memory is not being allocated so I get segmentation faults. Here is the code:
#include <stdio.h>
#include <stdlib.h>
//#include <cuda.h>
#include <math.h>
//#include "cublas.h"
//datatype to match FORTRAN complex type
typedef float real;
typedef struct{
int nx;
int ny;
int nz;
int sz;
int tz;
} states;
void set_SPB(real **,int,states **,states **,int **);
//void set_SPB();
int find_minimum(int a[], int n,int start);
const real hc =197.32697,pi=3.1415927;
int main(){
int nmax = 2, A = 28;
real *etemp, *fock;
int *Ndex,*lookup,*lookup_a;
states *channel,*SPB;
//!generates the single particle basis to be used
set_SPB(&etemp,nmax,&SPB,&channel,&Ndex);
free(etemp);
free(Ndex);
free(SPB);
return 0;
}
void set_SPB(real **etemp,int nmax,states **SPB,states **channel,int **Ndex){
int tot_orbs = (2*nmax+1)*(2*nmax+1)*(2*nmax+1)*4;
int D = tot_orbs/4;
int Nalpha = (2*nmax+1)*(2*nmax+1)*(2*nmax+1)*9;
real E;
*etemp = (real*)malloc(D);
*Ndex = (int*)malloc(D*3);
*SPB = (states*)malloc(tot_orbs);
printf("orbits without spin degeneracy %d \n",D);
printf("size of etemp %ld \n",sizeof(*etemp)/sizeof(*etemp[0]));
return;
int i = 0;
for(int nx =-nmax;nx<=nmax;nx++){
for(int ny =-nmax;ny<=nmax;ny++){
for(int nz =-nmax;nz<=nmax;nz++){
E = 0.5*4.0*pi*pi*(nx*nx+ny*ny+nz*nz);
//printf("%d\n",i);
*etemp[i] = E;
*Ndex[0*D+i] =nx;
*Ndex[1*D+i] = ny;
*Ndex[2*D+i] = nz;
i+=1;
}
}
}
return;
}
Also I am not sure exactly if my assignments of the arrays are correct.
Specifically the print to find the number of elements of that have been allocated always gives 2, when it should be D = 125.
I cannot believe that float and int take only 1 byte in your environment.
Multiply the size to be allocated by size of their elements.
*etemp = malloc(sizeof(**etemp) * D);
*Ndex = malloc(sizeof(**Ndex) * D*3);
*SPB = malloc(sizeof(**SPB) * tot_orbs); /* not sure because this is not used */
Note that they say you shouldn't cast the result of malloc() in C.
Also note that [] operator has higher precedence than * operator, so you have to use parentheses to use the arrays.
(*etemp)[i] = E;
(*Ndex)[0*D+i] =nx;
(*Ndex)[1*D+i] = ny;
(*Ndex)[2*D+i] = nz;