How to get values from a C Struct in python? - c

So I created golang code to pass a value to a C struct and then return it into a pointer so that I can get the value in py. But am I able to get the values from the C struct in py? If so, how can I? My main goal is to pass multiple values from go to the C struct then get those values in py. Also what is the right way to do this without any memory leaks?
Heres my go code:
package main
/*
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
typedef struct Resp {
char *response;
char *responsetwo;
} Resp;
void fill(Resp *r) {
printf("Original value: %s\n", r->response);
}
*/
import "C"
import (
"unsafe"
)
func body_string(body string, body_two string) unsafe.Pointer {
sb := C.CString(body)
sb_two := C.CString(body_two)
// adding it to the C struct
return &C.Resp{
response: sb,
responsetwo: sb_two,
}
}
I am not sure if this is the most efficient way, but is this okay for large text values? Thank you.

Related

Read the value of pointer to pointer array of struct passed to a function

Context:
Recently I've started programming in a more professional way and currently I'm working on a C driver library that should look decent in code both functionally and esthetically so I've just started to use the consept of pointers more intensely and not very experienced with it in relation to how it works on code.
Problem:
Basically I'm trying to read a values inside each of the struct with a for loop inside initFunt()
My solution to that was to create a struct pointer group for all the created btn_params_t instants and pass that pointer group to initFunc() and from init access each struct member with something like "Btn Pin in the first struct is: %d", BtnPointer[0]->BtnPin
Here's basically the code to explain it:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef struct btn_params_t
{
uint8_t BtnPin;
uint8_t BtnActiveState;
uint8_t BtnPinPullUp;
uint8_t BtnPinPullDown;
void (*PressedISR)();
void (*ReleasedISR)();
} btn_params_t;
void initFunc(btn_params_t **BtnPointer){
printf("Btn Pin in the first struct is: %d", BtnPointer[0]->BtnPin);
}
int main(int argc, char *argv[]) {
btn_params_t Btn0Params = {
.BtnPin = 4,
.BtnActiveState = 0,
.BtnPinPullUp = 1,
.BtnPinPullDown = 0
};
btn_params_t Btn1Params = {.BtnPin = 32};
btn_params_t** BtnGroup = {&Btn0Params, &Btn1Params};
initFunc(BtnGroup);
}
How'd you do such a thing?

Trouble Including Externally Declared Enumeration - C Code

Update: The issue is resolved. Here is code that compiles properly.
---instruction.h---
#ifndef INSTRUCTION_H
#define INSTRUCTION_H
typedef enum OPCODE {ADD = 0x20,ADDI = 0x8,SUB = 0x22,MULT = 0x18,BEQ = 0x4,LW = 0x23,SW = 0x2B} opcode;
/*opcode is OPCODEs alias*/
typedef struct INSTRUCTION {
opcode op;
int rs;
int rt;
int rd;
int Imm;
} inst;
/*inst is INSTRUCTIONs alias*/
#endif // INSTRUCTION_H
---parser.c---
#include <stdio.h>
#include "instruction.h"
void parser(char *instruction)
{
/*Parse character string into instruction components*/
inst set1 = {LW,0,1,2,0};
printf("parsing");
};
int main()
{
char *instruction;
instruction = NULL;
parser(instruction);
};
/*pass in pointer for instruction being passed in*/
/*pointing to address of instruction being passed in*/
/*Parser return type is struct inst*/
I cannot seem to get my enumeration type "opcode" to be recognized in my main c file. I included the header file. I am fairly new to C, so haven't made much ground on the issue for some time now and wanted to see if anyone knew why I was getting the error messages below. My guess is the linking the header file is not working properly. Any help is much appreciated.
---instruction.h----
#ifndef INSTRUCTION_H
#define INSTRUCTION_H
typedef enum {add = 32,addi = 8,sub = 34,mult = 24,beq = 4,lw = 35,sw = 43}opcode;
extern opcode oper;
typedef struct {
opcode op;
int rs;
int rt;
int rd;
int Imm;
}inst;
#endif // INSTRUCTION_H
---Parser.c---
#include <stdio.h>
#include "instruction.h"
void parser(char *inst)
{
/*Parse character string into instruction components*/
struct inst{lw,0,1,2,0};
};
int main()
{
char *instruction;
instruction = NULL;
parser(instruction);
};
struct inst{lw,0,1,2,0};
This looks like it's supposed to be a variable declaration, but I don't see a name for the variable. Try:
struct inst name_of_the_variable = {lw,0,1,2,0};
As a side note, enum values are global constants, so it's probably not a good idea to give them names like lw that can be confused for variables. Standard practice would be to use all-caps for the names and give them a prefix… say, OPCODE_ADD, OPCODE_LW, etc.
This is not a valid variable definition:
struct inst{lw,0,1,2,0};
There's no struct inst defined, only inst, there's no variable name, and you need = to use an initializer. To create a variable of this type an initialize it, you need:
inst myinst = {lw,0,1,2,0};
Also, your function has a parameter named inst which masks the type inst. You need to give it a different name:
void parser(char *instruction)

Is it possible to call functions from arrays in C? [duplicate]

This question already has answers here:
How can I use an array of function pointers?
(12 answers)
Closed 4 years ago.
When I was making my terminal i was wondering if I can call a function by array.
(This code is not done yet so please code is a bit messy.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <unistd.h>
#include <limits.h>
#define true 1
#define false 0
typedef int bool;
/* Static */
static char Input[CHAR_MAX];
static char CurrentDirectory[CHAR_MAX];
static char *Command;
static char *Argument;
static char *Commands[]={"test","test2"};
/* Functions */
int Check_Command();
int test();
int test2();
/* --------- */
int main(){
printf("#######################\n\tterminal\n\tType \"help\" for the list of commands\n#######################\n");
prompt:
printf(">");
fgets(Input,CHAR_MAX,stdin);
int res=Check_Command();
if(res==0){printf("Unknown Command!\n");}
goto prompt;
}
/* Check_Command() function returns 0 if doesn't suceed and returns 1 of it suceeds */
int Check_Command(){
//Since input variable is static, no need to send in arguments
Input[strcspn(Input,"\r\n")]=0;
Command=strtok(Input," ");
Argument=strtok(NULL," ");
int x=0;
while(x<sizeof(Commands)){
if(strcmp(Command,Commands[x])==0){
Commands[x](); <----- Can I call a function like this?
return 1;
}
x++;
}
return 0;
}
/* Commands */
int test(){
printf("Success!\n");
getchar();
exit(0);
}
int test2(){
print("Success [2] \n");
getchar();
exit(0);
}
If this possible then this would be lit, Im too lazy to make commands into a executable and using if statements for all commands.
if you are too lazy to read the whole code here is a basic concept (UNTESTED):
static *Commands[]={"test","test2"};
int main(){
char *Command="test";
int x=0;
while(x<sizeof(Commands)){
if(strcmp(Command,Commands)==0){
Commands[x]();
}
x++
}
}
int test(){
printf("Hi");
}
int test2(){
printf("hey");
}
Edit:
static char Commands[]={test,test2}; DOES NOT WORK
This also includes the "possible duplicate" answer. (Im using Mingw, Windows 10)
It appears that you want to be able to take in a string such as test2 from the user, and then invoke the function test2(). There are two main ways you can approach this:
Homebrew structure mapping names to function pointers.
Using 'dynamic library loading' and function name resolution.
Array of structures
For the first, you define a structure such as:
struct FuncName
{
const char *name;
int (*function)(void);
};
And you can then define an array of these:
struct FuncName functions[] =
{
{ "test", test },
{ "test2", test2 },
};
enum { NUM_FUNCTIONS = sizeof(functions) / sizeof(functions[0]) };
When you get a name from the user, you can search through the array of names and find the matching function pointer to call.
int invoke_function(const char *name)
{
for (int i = 0; i < NUM_FUNCTIONS; i++)
{
if (strcmp(name, functions[i].name) == 0)
{
return (*functions[i].function)();
// Or just: return functions[i].function();
}
}
return -1; // No match found
}
This works reliably on all systems, but the demerit is that you must create the table of function pointers when you compile the program.
Dynamic library
The alternative is to use functions dlopen() and dlsym() from the <dlsym.h> header on Unix (POSIX) systems, or the equivalent on Windows.
Normally, you expect to find the functions in dynamically loaded libraries loaded with dlopen(), but there's usually a way to search the main executable for the names instead (pass a null pointer as the file name to dlopen() on POSIX systems). You can then call dlsym() to get the function pointer corresponding to the name you specify, which you can call.
void *dlh = dlopen(NULL, RTLD_NOW);
int (*funcptr)(void) = (int (*)(void))dlsym("test", dlh);
return (*funcptr)();
This omits error checking and you need the cast to convert from an object pointer (void *) to a function pointer because the C standard does not require that to be doable, but POSIX does (see the specification of
dlsym() already linked to).
Non-uniform function signatures
With both solutions, life is easy if all the callable functions have the same interface. Life is much messier if the different functions have different interfaces (so some expect no arguments, some expect one, some expect two, and the types of the arguments vary between functions, as do the return types). Expect to use lots of casts and be prepared to bludgeon the compiler into submission — isolate the code from everything else so as to leave the non-portable part well separated from the main code.
Beware: no compiler was consulted about the validity of any of this code!

C pointer casting to and from Go

I'm writing an app for the windows platform using FFmpeg and it's golang wrapper goav, but I'm having trouble understanding how to pass the C pointers between C and Go.
I've stripped out all the relevant parts of the C code, the wrapper and my code, shown below:
C code - libavutil/frame.h
#include <stdint.h>
typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8
uint8_t *data[AV_NUM_DATA_POINTERS];
}
Go goav wrapper
package avutil
/*
#cgo pkg-config: libavutil
#include <libavutil/frame.h>
#include <stdlib.h>
// C code I added:
#include <stdio.h>
void SaveFrame(const char* location, uint8_t *data, int width, int height) {
FILE *pFile;
int y;
// Open file
pFile=fopen(location, "wb");
if(pFile==NULL)
return;
// Write header
fprintf(pFile, "P6\n%d %d\n255\n", width, height);
// Write pixel data
for(y=0; y<height; y++)
fwrite(data+y*width, 1, width*3, pFile);
// Close file
fclose(pFile);
}
*/
import "C"
import (
"unsafe"
)
type Frame C.struct_AVFrame
func Data(f *Frame) *uint8 {
// i think this is the function thats not working?
return (*uint8)(unsafe.Pointer((*C.uint8_t)(unsafe.Pointer(&f.data))))
}
func SaveFrame(location string, data *uint8, width int, height int) {
C.SaveFrame(C.CString(location), unsafe.Pointer(data), C.int(width), C.int(height))
}
My Go code
package main
import "github.com/giorgisio/goav/avutil"
func main() {
var frame *avutil.Frame
var data *uint8
//... initialize frame
data = avutil.Data(frame)
avutil.SaveFrame("frame0.ppm", data, 1920, 1080)
}
When I try to save the frame, the resulting image is garbled because the pointer is wrong, how do i fix this?
The data field of the AVFrame struct is an array of 8 pointers.
That is, it's a contiguous chunk of memory containing 8 slots
adjacent to each other—each holding a pointer (to a value of type uint8_t).
IOW, the declaration
uint8_t *data[AV_NUM_DATA_POINTERS];
is better interpreted as
uint8_t* data[AV_NUM_DATA_POINTERS];
and in Go, you'd declare it something like
var data [AV_NUM_DATA_POINTERS]*uint8_t
Now your SaveFrame function declares its data arguments to
be of type uint8_t*. That is okay to pass the address of the
data array of an AVFrame struct as that argument, but more idiomatic
would be to pass the address of its zeroth element—something like
func Data(frame *Frame) *uint8 {
return (*uint8)(unsafe.Pointer(&frame.data[0]))
}

How to cast bytes to struct(c struct) in go?

package main
/*
#define _GNU_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <utmpx.h>
#include <fcntl.h>
#include <unistd.h>
char *path_utmpx = _PATH_UTMPX;
typedef struct utmpx utmpx;
*/
import "C"
import (
"fmt"
"io/ioutil"
)
type Record C.utmpx
func main() {
path := C.GoString(C.path_utmpx)
content, err := ioutil.ReadFile(path)
handleError(err)
var records []Record
// now we have the bytes(content), the struct(Record/C.utmpx)
// how can I cast bytes to struct ?
}
func handleError(err error) {
if err != nil {
panic("bad")
}
}
I'm trying to read content into Record
I have asked a few related questions.
Cannot access c variables in cgo
Can not read utmpx file in go
I have read some articles and posts but still cannot figure out a way to do this.
I think you're going about this the wrong way. If you were wanting to use the C library, you would use the C library to read the file.
Don't use cgo purely to have struct definitions, you should create these in Go yourself. You could then write the appropriate marshal / unmarshal code to read from the raw bytes.
A quick Google shows that someone has already done the work required to convert a look of the relevant C library to Go. See the utmp repository.
A short example of how this could be used is:
package main
import (
"bytes"
"fmt"
"log"
"github.com/ericlagergren/go-gnulib/utmp"
)
func handleError(err error) {
if err != nil {
log.Fatal(err)
}
}
func byteToStr(b []byte) string {
i := bytes.IndexByte(b, 0)
if i == -1 {
i = len(b)
}
return string(b[:i])
}
func main() {
list, err := utmp.ReadUtmp(utmp.UtmpxFile, 0)
handleError(err)
for _, u := range list {
fmt.Println(byteToStr(u.User[:]))
}
}
You can view the GoDoc for the utmp package for more information.

Resources