Skip to content

Instantly share code, notes, and snippets.

@palaniraja
Last active February 11, 2025 20:21
Show Gist options
  • Save palaniraja/3589803be3bfac1f9a158f1ceba84d09 to your computer and use it in GitHub Desktop.
Save palaniraja/3589803be3bfac1f9a158f1ceba84d09 to your computer and use it in GitHub Desktop.
cgo sample
package main
/*
#cgo CFLAGS: -I.
#cgo LDFLAGS: -L. -lstudent
#include <stdlib.h>
#include <string.h>
#include "student.h"
*/
import "C"
import (
"fmt"
"unsafe"
)
// Go enum for Gender
type Gender int
const (
Male Gender = iota
Female
)
// Go struct for Student
type Student struct {
Firstname string
Lastname string
Age int
Weight float32
Gender Gender
}
func main() {
// Create an array of students
students := []Student{
{"John", "Doe", 16, 82.5, Male},
{"Jane", "Smith", 14, 75.0, Female},
{"Alice", "Johnson", 17, 82.5, Female},
}
// Convert Go students to C students
cStudents := make([]C.Student, len(students))
for i, s := range students {
firstname := C.CString(s.Firstname)
lastname := C.CString(s.Lastname)
defer C.free(unsafe.Pointer(firstname))
defer C.free(unsafe.Pointer(lastname))
C.strncpy(&cStudents[i].firstname[0], firstname, C.size_t(len(cStudents[i].firstname)-1))
C.strncpy(&cStudents[i].lastname[0], lastname, C.size_t(len(cStudents[i].lastname)-1))
cStudents[i].age = C.int(s.Age)
cStudents[i].weight = C.float(s.Weight)
cStudents[i].gender = C.Gender(s.Gender)
}
var filteredStudents *C.Student
var numFiltered C.int
// Call the C function
C.filter_students(&cStudents[0], C.int(len(cStudents)), 15, 82.5, &filteredStudents, &numFiltered)
// Convert filtered C students back to Go students
goFilteredStudents := make([]Student, numFiltered)
for i := 0; i < int(numFiltered); i++ {
student := (*[1 << 30]C.Student)(unsafe.Pointer(filteredStudents))[i]
goFilteredStudents[i] = Student{
Firstname: C.GoString(&student.firstname[0]),
Lastname: C.GoString(&student.lastname[0]),
Age: int(student.age),
Weight: float32(student.weight),
Gender: Gender(student.gender),
}
}
// Print the filtered students
fmt.Println("Filtered Students:")
for _, s := range goFilteredStudents {
fmt.Printf("==> %s %s, Age: %d, Weight: %.1f, Gender: %v\n", s.Firstname, s.Lastname, s.Age, s.Weight, s.Gender)
}
// Free the allocated memory
C.free(unsafe.Pointer(filteredStudents))
}
CC := clang
CXX := clang++
CFLAGS := -g -O0 -Wall -fPIC -std=c11
CXXFLAGS := -g -O0 -Wall -fPIC -std=c++17
# static .a lib
# LDFLAGS := -g
# GO_BUILD_FLAGS := -gcflags="all=-N -l" -ldflags="-extldflags '$(LDFLAGS) -lc++'"
#shared .so/.dylib
LDFLAGS := -g -shared
GO_BUILD_FLAGS := -gcflags="all=-N -l"
all: build
clean:
rm -rf *.o *.a *.so *.dylib main *.dSYM
compile-c:
$(CC) -c student.c -o student.o
# comment below line if you are building shared lib
# ar rcs libstudent.a student.o
# for shared lib
$(CC) $(LDFLAGS) -o libstudent.so student.c
build: compile-c
CGO_CXXFLAGS="$(CXXFLAGS)" go build $(GO_BUILD_FLAGS) main.go
run: compile-c
CGO_CXXFLAGS="$(CXXFLAGS)" go run $(GO_BUILD_FLAGS) main.go
#include "student.h"
#include <stdlib.h>
#include <string.h>
void filter_students(Student *students, int num_students, int age_filter, float weight_filter, Student **filtered_students, int *num_filtered) {
*num_filtered = 0;
*filtered_students = (Student *)malloc(num_students * sizeof(Student));
for (int i = 0; i < num_students; i++) {
if (students[i].age >= age_filter && students[i].weight == weight_filter) {
(*filtered_students)[*num_filtered] = students[i];
(*num_filtered)++;
}
}
}
#ifndef STUDENT_H
#define STUDENT_H
typedef enum {
MALE,
FEMALE
} Gender;
typedef struct {
char firstname[50];
char lastname[50];
int age;
float weight;
Gender gender;
} Student;
void filter_students(Student *students, int num_students, int age_filter, float weight_filter, Student **filtered_students, int *num_filtered);
#endif // STUDENT_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment