Nim import typedef from C header file - ffi

I'm wondering if I can import a C type definition or if I need to redefine it in Nim?
Looking at program called jhead interfacing with this proc
int ReadJpegFile(const char * FileName, ReadMode_t ReadMode);
The second parameter ReadMode_t is an enum type in jhead.h
typedef enum {
READ_METADATA = 1,
READ_IMAGE = 2,
READ_ALL = 3,
READ_ANY = 5 // Don't abort on non-jpeg files.
}ReadMode_t;
Can I import this ReadMode_t? Or do I have to redfine it like below
type
ReadMode_t* = enum
READ_METADATA = 1, READ_IMAGE = 2, READ_ALL = 3, READ_ANY = 5

The Nim compiler needs to know about those C constants, so you have to define them to use them from Nim. However, this tedious copying can be simplified and even automated to some degree with tools like c2nim. In fact, if you take the following test.h file:
typedef enum {
READ_METADATA = 1,
READ_IMAGE = 2,
READ_ALL = 3,
READ_ANY = 5 // Don't abort on non-jpeg files.
}ReadMode_t;
int ReadJpegFile(const char * FileName, ReadMode_t ReadMode);
and run c2nim test.h, it will generate the following test.nim file for you, saving most of the tedious translation:
type
ReadMode_t* = enum
READ_METADATA = 1, READ_IMAGE = 2, READ_ALL = 3, READ_ANY = 5
proc ReadJpegFile*(FileName: cstring; ReadMode: ReadMode_t): cint

Related

C Nested Structs Initialization

I'm an avid embedded c programmer. I recently started working with the ESP IDF framework to program the ESP32. Even though I think that the following code is initializing a struct within a struct (not sure); but for some reason, I cannot grasp how and why there is just a ".mode" rather than the struct's name within gpio_config_t + ".mode". This is just an example but there are several instances of similar types of initialization.
for example:
typedef struct example_struct{
int mode;
int pull_up_en;
.
.
}example_struct;
typedef struct gpio_config_t
{
example_struct test;
} gpio_config_t;
Shouldn't the initialization be done the following way?
gpio_config_t io_test_config =
{
test.mode = 3;
test.pull_up_en = 1;
etc
};
Can someone please clarify this?
The actual type of initialization I'm referring to:
gpio_config_t io_conf = {
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = 1,
};
The technical term for the notation you're using is designated initializers. The designators always start with either a . or a [, and there are no semicolons in the initializers (until after the } at the end of the initializer). There are many ways that you could initialize that structure, including:
gpio_config_t io_test_config1 =
{
.test.mode = 3, .test.pull_up_en = 1
};
gpio_config_t io_test_config2 =
{
.test = { .mode = 3, .pull_up_en = 1 }
};
gpio_config_t io_test_config3 =
{
{ 3, 1 }
};
gpio_config_t io_test_config4 =
{
3, 1
};
The last one doesn't compile cleanly with GCC when you specify -Wmissing-braces (usually activated by -Wall).

ctypes Structure strange behaviour?

I'm defining my structure in python according to the docs (or so I think) but when calling the c function the values don't match:
Python code:
print(f"SchemaID:{appHandResp.supportedAppProtocolRes.SchemaID}, SchemaID_isUsed:{appHandResp.supportedAppProtocolRes.SchemaID_isUsed}")
errn = openv2g.encode_appHandExiDocument(byref(oStream), byref(appHandResp))
C code:
int encode_appHandExiDocument(bitstream_t* stream, struct appHandEXIDocument* exiDoc) {
if (exiDoc->supportedAppProtocolRes_isUsed)
printf("SchemaID:%d, SchemaID_isUsed:%d\n", exiDoc->supportedAppProtocolRes.SchemaID, exiDoc->supportedAppProtocolRes.SchemaID_isUsed);
Output:
# in Python right before calling the C function
SchemaID:2, SchemaID_isUsed:1
# in the C function
SchemaID:1, SchemaID_isUsed:0
The structure definitons:
# Python3.8
appHandresponseCodeType = ctypes.c_uint8
appHandresponseCodeType_OK_SuccessfulNegotiation,\
appHandresponseCodeType_OK_SuccessfulNegotiationWithMinorDeviation,\
appHandresponseCodeType_Failed_NoNegotiation = map(appHandresponseCodeType, range(3))
class appHandAnonType_supportedAppProtocolRes(ctypes.Structure):
_fields_ = [
("ResponseCode", appHandresponseCodeType),
("SchemaID", ctypes.c_uint8),
("SchemaID_isUsed", ctypes.c_uint, 1),
]
.
// C
typedef enum {
appHandresponseCodeType_OK_SuccessfulNegotiation = 0,
appHandresponseCodeType_OK_SuccessfulNegotiationWithMinorDeviation = 1,
appHandresponseCodeType_Failed_NoNegotiation = 2
} appHandresponseCodeType;
struct appHandAnonType_supportedAppProtocolRes {
appHandresponseCodeType ResponseCode ;
uint8_t SchemaID ;
unsigned int SchemaID_isUsed:1;
};
Playing with the structure definition in python I was able to get the expected result:
appHandresponseCodeType = ctypes.c_uint
appHandresponseCodeType_OK_SuccessfulNegotiation,\
appHandresponseCodeType_OK_SuccessfulNegotiationWithMinorDeviation,\
appHandresponseCodeType_Failed_NoNegotiation = map(appHandresponseCodeType, range(3))
class appHandAnonType_supportedAppProtocolRes(ctypes.Structure):
_fields_ = [
("ResponseCode", appHandresponseCodeType),
("SchemaID", ctypes.c_uint8),
("SchemaID_isUsed", ctypes.c_uint8),
]
Output:
# in Python right before calling the C function
SchemaID:2, SchemaID_isUsed:1
# in the C function
SchemaID:2, SchemaID_isUsed:1
I can't explain why this is the case, am I defining my structure in ctypes wrong?
Not 100%, but I think that this shows the underlying problem:
#include <stdio.h>
typedef struct A {
char x;
unsigned y:1;
} A;
int main() {
printf("%zu\n", sizeof(A));
return 0;
}
prints the value '4' using clang/macos/64bit, gcc/linux/64bit. It is because of the bitfield permitting the compiler to compact the structure.
This should work for you. A C enum is equivalent to a c_int. You don't need to cast the enum values. Just assign them to ResponseCode as needed. It is odd to use a bitfield for a single bit. That one bit will still occupy a full c_uint (typically 32-bits) anyway. There will also normally be three padding bytes between the c_uint8 and the next c_uint for alignment purposes, unless you also set _pack_ as well (must be before _fields_ if used). Check the C header for any packing directives.
from ctypes import *
appHandresponseCodeType_OK_SuccessfulNegotiation = 0
appHandresponseCodeType_OK_SuccessfulNegotiationWithMinorDeviation = 1
appHandresponseCodeType_Failed_NoNegotiation = 2
class appHandAnonType_supportedAppProtocolRes(Structure):
# _pack_ = 1 # if needed, uncomment.
_fields_ = (('ResponseCode',c_int),
('SchemaID',c_uint8),
('SchemaID_isUsed',c_uint,1))

Clang-format: how to format C struct initializer this way

I'm using the linux kernel .clang-format as a reference, but this part is bothering me.
How can I get clang-format to format this code
const struct my_struct hello = {.id = 0,
.modsmin = 10,
.modsmax = 20,
.strengthmin = 0,
.strengthmax = 100,
.color = COLOR_FOREGROUND };
to this
const struct my_struct hello = {
.id = 0,
.modsmin = 10,
.modsmax = 20,
.strengthmin = 0,
.strengthmax = 100,
.color = COLOR_FOREGROUND
};
Looking at the documentation, there don't seem to be any clang-format style options which will do what you want.
But, you can use the "comma-after-last-item" trick. Put a comma after the last designated initializer, before the final closing brace. I believe this is still valid C code. Then clang-format will put each initializer on a separate line, and this will move the indentation back to what you're looking for. So the output would look like this:
const struct my_struct hello = {
.id = 0,
.modsmin = 10,
.modsmax = 20,
.strengthmin = 0,
.strengthmax = 100,
.color = COLOR_FOREGROUND,
};
This behavior is not documented anywhere (as far as I know), so I suppose it could be changed in the future. But this behavior has been there for many years and many versions of clang-format so I think it is reasonable to rely on it.

Initialize an array in C

Since it's not possible to assign values to a const after it's initialized, how can I achieve this?
const double input1[1000][2];
for(int i = 0; i < 1000; i++){
input1[i][0] = i;
input1[i][1] = i*2;
}
You'll have to generate the explicit initialization (i.e. the { {0, 0}, {1, 2}, {2, 4}, ... etc etc ... {1000, 2000} }.
You can do this with map/apply macros, or with your build system - having it run some script which generates that initialization sequence and plants it into the file.
You mentioned in the comments that this data is a training session data for a neural network.
I assume that you don't want to input 2000 values by hand and I assume that these values
come from another file, perhaps a csv or the output of another program that
generates the training data.
In that case, I'd write a script that generates a header file from the training
data that looks like this:
// training_data.h
// trainng data, automatically generated by script gen_training_data.py
// do not modify this file
#ifndef TRAINING_DATA_H
#define TRAINING_DATA_H
const double traing_data[1000][2] = {
{ 0, 1 },
{ 0, 2 },
....
};
#endif
The script (that you can write with other languages, bash, python, perl) would
take the training data and generate the header file for you, so you don't have
to write 2000 values by hand. Then you can use it in your C program like this:
#include <stdio.h>
#include "training_data.h" // include auto generated file
int main(void)
{
...
feed_to_neural_network(training_data);
...
}
If you use a build system like cmake, you can let cmake execute your script so
that it autogenerates the header file before compiling. That would save you on
the long run a lot of time.
I don't understand why would you want to store the index value in the first index. But removing const can solve your issue. But better thing to do would be, to just store the value instead of index. Like following:
double input1[1000];
for (int i = 0; i < 1000; i++)
{
input1[i] = i * 2;
}

How do I suppress PC-Lint errors for C99-style initialization of structure members?

I am using PC-Lint 8.00x with the following options:
+v -wlib(1) +fan +fas
I receive a number of error messages from PC-Lint when I run code similar to the following:
typedef union
{
struct
{
unsigned int a : 4;
unsigned int b : 4;
unsigned int c : 4;
unsigned int d : 4;
} bits;
unsigned short value;
} My_Value;
int main (void)
{
My_Value test[] =
{
{
.bits.a = 2,
.bits.b = 3, //Errors 133 and 10
.bits.c = 2,
.bits.d = 3,
},
{
.bits.a = 1,
.bits.b = 1, //Errors 133 and 10
.bits.c = 1,
.bits.d = 0,
},
};
/* Do something meaningful. */
return 0;
}
The reported errors are defined by PC-Lint as follows:
Error 133: Too many initializers for aggregate 'unknown-name'
Error 10: Expecting '}'
I have tried searching Gimpel and have done some Google searches, but I cannot find anything useful. The code functions as intended and everything initializes properly. Here are my questions.
1. Does PC-Lint 8.00x support C99 style initialization of structure members?
2. If so, what options/flags do I have to set for PC-Lint to suppress these messages globally?
EDIT
I should have been more detailed in regards to question 2. I would like to globally suppress these messages in regards to my usage of designated initializers as shown above. I cannot suppress them globally for all situations as these errors can detect true errors in the code.
As far as I can tell, this syntax:
My_Value test[] =
{
{
.bits.a = 2,
.bits.b = 3,
.bits.c = 2,
.bits.d = 3,
},
{
.bits.a = 1,
.bits.b = 1,
.bits.c = 1,
.bits.d = 0,
},
};
is valid in C99 (and C11). Looking in section 6.7.8 of the standard, the thing preceding the = in an initializer is a designator-list, which is a sequence of one or more designators. .bits.a is valid in that context.
Apparently PC-Lint doesn't support that syntax. (You might want to notify the maintainers, unless it's already supported in a later version.)
As a workaround, if you change it to this:
My_Value test[] =
{
{ .bits =
{
.a = 2,
.b = 3,
.c = 2,
.d = 3,
},
},
{ .bits =
{
.a = 1,
.b = 1,
.c = 1,
.d = 0,
},
},
};
it's still valid C (and arguably clearer) and, based on what you just wrote in a comment, PC-Lint accepts it.
(If you want to be even more explicit, you might consider adding [0] = and [1] = designators.)
UPDATE : QUoting a new commment:
The good people at Gimpel software have responded stating that "this
appears to be a bug" and are working to correct it.
Not sure to the C99 and 8.00x support question, as I have 9.00k installed. But 9.00k dislikes your form of union initialization, but Visual Studio has no issue.
But for Jacchim Pileborg's case it just emits a Info 708: union initialization while might be safer to turn off.
As noted in the comments you dont want to fully globally remove these error types, so -e133 and -e10 will not solve your problems.
So using Joachim's form, I can using a macro suppress it like so:
typedef union
{
struct
{
unsigned int a : 4;
unsigned int b : 4;
unsigned int c : 4;
unsigned int d : 4;
} bits;
unsigned short value;
} My_Value;
#define MY_UNION(A,B,C,D) /*lint -save -e708*/{{.a=(A),.b=(B),.c=(C),.d=(D)}}/*lint -restore*/
int main(void)
{
My_Value test[] =
{
MY_UNION(2, 3, 2, 1),
MY_UNION(1, 2, 3, 4)
};
return 0;
}
Ugly, but as you have nothing to make the lint commands to stick to as it's all anonymous, you ether have to put inline commands explicitly or via a macro.

Resources