C pointer casting to and from Go - c

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]))
}

Related

How to get values from a C Struct in python?

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.

Declare a pointer to structure in const expression

I am new to C and can't yet freely navigate trough my program memory. Anyways, I am creating a static memory data type (gc_menu) that should hold a pointer to created at execution time structure (mcl_items).
For simplicity mcl_items structure have one virtual method (push) that is going to be run inside of gc_menu_add_item and also assigned to the gc_menu static space. push saves an menu item name (letter) and method to mcl_item virtual object.
mcl_items.h code:
[...]
typedef struct Items_t {
int8_t size;
char names[64];
void (*methods[64])();
// Interface
void (*push)(struct Items_t *self, char c, void (*method)());
}mcl_items;
mcl_items *new_mcl_items();
void mcl_items_push(mcl_items *self, char c, void (*method)());
mcl_items.c code:
[...]
#include "mcl_items.h"
mcl_items *new_mcl_items() {
fprintf(stderr, "MCL_Items: Generating a new set of mcl_items..");
// Build a virtual object
mcl_items *items = calloc(1, sizeof(struct Items_t));
items->push = mcl_items_push;
// Set data
items->size = 0;
return items;
}
void mcl_items_push(mcl_items *self, char c, void (*method)()) {
fprintf(stderr, "MCL_Items: pushing a new item..");
self->names[self->size] = c;
self->methods[self->size] = method;
self->size ++;
}
gc_menu.h code:
#include "items.h"
typedef struct {
// Interface
void (*add_item)(char c, void (*method)());
// Data
mcl_items *items;
}__gc_menu;
extern __gc_menu const gc_menu;
gc_menu.c code:
static void gc_menu_add_item(char c, void (*method)) {
fprintf(stderr, "GC_Menu: Passing an new item..");
fprintf(stderr, "length = %i\n", gc_menu.items->size);
gc_menu.items->push(gc_menu.items, c, method);
}
__gc_menu const gc_menu = {gc_menu_add_item, // Virtual methods
new_mcl_items}; // Data
After callng gc_menu.add_item the segmentation fault occurs and gc_menu.items->size is equal to 72, not 0 as is defined in the definition of new_mcl_items.
main.c code:
gc_menu.add_item('q', xw->end(xw));
GC_Menu: Passing an new item..length = 72
[1] 66021 segmentation fault (core dumped) ./3D_scean
So what am I doing wrong? Why is there such a weird data written to instances of my gc_menu.items?
You've initialized gc_menu.items to new_mcl_items, i.e. a pointer to the function new_mcl_items (which should give you a warning since it is of type mcl_items *(*)(void) and not mcl_items *).
It looks like what you want is to actually call the function new_mcl_items() and set gc_menu.items to the value that new_mcl_items() returns. You can't do this with an initializer; initializers of global or static objects must be known at compile or link time. Standard C doesn't have "constructors".
So you'll have to remove the const from the declaration and definition of gc_menu, and add code to main (or some function called by main, etc) to initialize gc_menu.items at run time.
gc_menu.h:
extern __gc_menu gc_menu;
gc_menu.c:
__gc_menu gc_menu = {
gc_menu_add_item,
NULL // or whatever else you like
};
main.c or whatever you have called it:
int main(void) {
// ...
gc_menu.items = new_mcl_items();
// ...
}

How to use MagickGetImageHistogram of ImageMagick C API

I have been using ImageMagick's C API using LuaJIT and FFI library and magick lua module for this. Now I want to use MagickGetImageHistogram method. So when it comes to pass an argument check my below code.
***image.lua***
local len = ffi.new("size_t[?]", 5)
local t = handle_result(self, lib.MagickGetImageHistogram(self.wand, len))
***lib.lua***
local ffi = require("ffi")
local lib
ffi.cdef([[ typedef void MagickWand;
typedef void PixelWand;
typedef int MagickBooleanType;
typedef int ExceptionType;
typedef int ssize_t;
typedef int CompositeOperator;
typedef int GravityType;
typedef int OrientationType;
typedef int InterlaceType;
typedef char DistortMethod[];
void MagickWandGenesis();
MagickWand* NewMagickWand();
PixelWand **MagickGetImageHistogram(MagickWand *wand, size_t *number_colors);
So I'm sure that my first argument is correct but not sure about second one.
And it returns the image histogram as an array of PixelWand wands. So how do I convert it to LuaJIT structure?
I'm not sure about the lua parts of the question, but the expected behavior MagickGetImageHistogram is as follows.
Method will return an array of pixel pointers.
Argument size_t *number_colors will be updated with the count of pixels in array.
Each pixel in array will need to invoke method PixelGetColorCount to retrieve the sum of pixels used by image.
Here's a quick example in C.
#include <stdio.h>
#include <wand/MagickWand.h>
int main(int argc, const char * argv[]) {
// Prototype vars
MagickWand * wand;
PixelWand ** histogram;
size_t histogram_count = 0;
// Boot environment.
MagickWandGenesis();
// Allocate & read image
wand = NewMagickWand();
MagickReadImage(wand, "rose:");
// Get Histogram as array of pixels
histogram = MagickGetImageHistogram(wand, &histogram_count);
// Iterate over each pixel & dump info.
for (int i = 0; i < histogram_count; ++i)
{
printf("%s => %zu\n",
PixelGetColorAsString(histogram[i]),
PixelGetColorCount(histogram[i]));
}
// Clean-up
histogram = DestroyPixelWands(histogram, histogram_count);
wand = DestroyMagickWand(wand);
MagickWandTerminus();
return 0;
}
This example will output the expected text...
// ...
srgb(48,45,43) => 1
srgb(50,45,42) => 2
srgb(50,44,43) => 5
srgb(51,45,43) => 1
// ...
So I would guess your lua script would look something like..
***image.lua***
local tlen = ffi.new("size_t[1]")
local t = lib.MagickGetImageHistogram(self.wand, tlen)
for i=0,tlen[0] do
handle_new_pixel(self, t[i], lib.PixelGetColorCount(t[i]))
end

Compiler Error in C: expected ')' before '*' token

As the title says, keep getting this error when trying to compile. From Googling this error people have said that it is not declared in the header file but my function is static and it is not in a header file, I prototyped it.`
#include <recGbl.h>
#include <devSup.h>
#include <devLib.h>
#include <drvIpac.h>
#include <dbScan.h>
#include <epicsExport.h>
static int cardinit(cardinfo *card); // <-- line that gives the error
typedef struct cardinfo{
struct cardinfo *next;
struct io_mem_read *pMem; /* IP register (A16) mem address */
word *rambase; /* RAM conversion memory mem address*/
int isconfigured;
int doram; /* 1 if we are using the RAM to output data.
0 if we are writing to registers (AO style) */
int cardnum;
int vmeslotnum;
int ipslotnum;
/* these values mirror the hardware registers */
word csr;
word offset;
word numconv;
word clockrate;
word vectnum;
word dacval[MAXSIGNAL];
word oldispresent;
/* used to detect a reinsertion of a carrier card.
see subroutine ispresent() below. */
/* use to update process variables */
IOSCANPVT ioscanpvt;
} cardinfo;
static int Hy8402init(int vmeslot, int ipslot, int clockrate) {
cardinfo *card;
card->vmeslotnum = vmeslot;
card->ipslotnum = ipslot;
card->cardnum = 1;
card->clockrate = clockrate;
card->vectnum = 10;
cardinit(card);
return TRUE;
}
static int cardinit(cardinfo *card){
word rprobe;
int res;
volatile word *ramptr;
card->pMem= ipmBaseAddr(card->vmeslotnum,
card->ipslotnum,ipac_addrIO);
if (card->pMem==NULL){
printf("Error in %s",devstr);
printf( "%s: Cannot determine base address\n",devstr);
return FALSE;
}
res=devReadProbe(sizeof (word),(char *) card->pMem,(char *) &rprobe);
if (res!=OK){
printf("%s: NO DEVICE at %x (vmeslot %d, ipslot %d)\n",devstr,
(int)card->pMem,
card->vmeslotnum,card->ipslotnum);
return FALSE;
}
return TRUE;
}
`
cardinfo struct is still undefined on the line with error. Put a forward declaration before it:
struct cardinfo;
static int cardinit(struct cardinfo *card);
This line of code:
static int cardinit(cardinfo *card);
should be added after the definition of your cardinfo structure.
You need to put the line
static int cardinit(cardinfo *card);
after the definition of the cardinfo structure.
At that line, the compiler doesn't yet know that cardinfo is a struct. Precede it with the line struct cardinfo;
You have declared a function which has a input variable of a type which the compiler is not aware when it parses it. i.e the struct defintion follows your function declaration.
So please do a forward declaration of the structure when you want to compile such code.
In computer programming, a forward declaration is a declaration
of an identifier (denoting an entity such as a type, a variable, or a
function) for which the programmer has not yet given a complete definition.
This link has a nice article on when full declarations are not required.

Trouble with Unions in C program

I am working on a C program that uses a Union. The union definition is in FILE_A header file and looks like this...
// FILE_A.h****************************************************
xdata union
{
long position;
char bytes[4];
}CurrentPosition;
If I set the value of CurrentPosition.position in FILE_A.c and then call a function in FILE_B.c that uses the union, the data in the union is back to Zero. This is demonstrated below.
// FILE_A.c****************************************************
int main.c(void)
{
CurrentPosition.position = 12345;
SomeFunctionInFileB();
}
// FILE_B.c****************************************************
void SomeFunctionInFileB(void)
{
// After the following lines execute I see all zeros in the flash memory.
WriteByteToFlash(CurrentPosition.bytes[0];
WriteByteToFlash(CurrentPosition.bytes[1];
WriteByteToFlash(CurrentPosition.bytes[2];
WriteByteToFlash(CurrentPosition.bytes[3];
}
Now, If I pass a long to SomeFunctionInFileB(long temp) and then store it into CurrentPosition.bytes within that function, and finally call WriteBytesToFlash(CurrentPosition.bytes[n]... it works just fine.
It appears as though the CurrentPosition Union is not global. So I tried changing the union definition in the header file to include the extern keyword like this...
extern xdata union
{
long position;
char bytes[4];
}CurrentPosition;
and then putting this in the source (.c) file...
xdata union
{
long position;
char bytes[4];
}CurrentPosition;
but this causes a compile error that says:
C:\SiLabs\Optec Programs\AgosRot\MotionControl.c:76: error 91: extern definition for 'CurrentPosition' mismatches with declaration.
C:\SiLabs\Optec Programs\AgosRot\/MotionControl.h:48: error 177: previously defined here
So what am I doing wrong? How do I make the union global?
Is FILE_A.h really MotionControl.h? If so I think the fix is to define a union type in the header:
typedef
union xdata
{
long position;
char bytes[4];
} xdata;
And declare a global variable of that type elsewhere in a header file (maybe the same one):
extern xdata CurrentPosition; // in a header file
Finally define the global variable in a C file exactly once. Maybe in file_a.c:
xdata CurrentPosition;
Of course a better fix might be to pass the xdata variable you want to write out to flash to SomeFunctionInFileB() so you don't have to depend on a global variable, which are well known to be problematic when not very, very carefully used. And there seems to be no good reason to not pass the data as a parameter:
// in a header file
void SomeFunctionInFileB( xdata const* pPosition);
void SomeFunctionInFileB( xdata const* pPosition)
{
// After the following lines execute I see all zeros in the flash memory.
WriteByteToFlash(pPosition->bytes[0];
WriteByteToFlash(pPosition->bytes[1];
WriteByteToFlash(pPosition->bytes[2];
WriteByteToFlash(pPosition->bytes[3];
}
And call it like so:
int main.c(void)
{
CurrentPosition.position = 12345;
SomeFunctionInFileB( &CurrentPosition);
}
Ideally you need a typedef for the union and an extern declaration in FILE_A.h and the actual definition of the union in FILE_A.c.
-
// FILE_A.h
typedef union
{
long position;
char bytes[4];
} Position;
extern Position CurrentPosition; // declaration
-
// FILE_A.c
#include "FILE_A.h"
Position CurrentPosition; // definition
int main(void)
{
CurrentPosition.position = 12345;
SomeFunctionInFileB();
return 0;
}
-
// FILE_B.c
#include "FILE_A.h"
void SomeFunctionInFileB(void)
{
// now there will be valid data in the flash memory.
WriteByteToFlash(cp.bytes[0];
WriteByteToFlash(cp.bytes[1];
WriteByteToFlash(cp.bytes[2];
WriteByteToFlash(cp.bytes[3];
}
-
You haven't instantiated the union.
You need :
// FILE_A.c****************************************************
#include "File_a.h"
CurrentPosition cp;
int main(void)
{
cp.position = 12345;
SomeFunctionInFileB();
}
// FILE_B.c****************************************************
#include "File_a.h"
extern CurrentPosition cp;
void SomeFunctionInFileB(void)
{
// now there will be valid data in the flash memory.
WriteByteToFlash(cp.bytes[0];
WriteByteToFlash(cp.bytes[1];
WriteByteToFlash(cp.bytes[2];
WriteByteToFlash(cp.bytes[3];
}
If sizeof(long) is not 4, then endianess comes into play...
consider
union{
long position
char bytes[sizeof long];
}

Resources