I am trying to import a C array that is 64kb meant to be a circular buffer for a log on a device. When I attempt to access this array in Swift I am met with the error
Value of type 'logging' has no member 'data'
To attempt to answer potential questions about bridging, I am using other types from my imported C library that are defined in the same file that this mock code originates.
The code is setup as follows:
logging.h:
typedef struct _logging {
uint8_t data[64*1024];
} logging;
In ReadLog.swift:
struct ReadLog {
var log: logging = logging()
func read() {
//...Do some stuff...
let char = log.data.0 // <- Error here 'Value of type 'logging' has no member 'data'
}
}
Changing the size of data to 256 imported this member with no issue. (I don't know what the cutoff is).
What would be the best way to handle this?
The problem is that C arrays are imported to Swift as a tuple, and tuples have a maximal arity (see for example What is the limit (if any) to the tuple cardinality in Swift?). The current limit in Swift 5 seems to be 4096 tuple elements.
A possible workaround is to create a C helper function which returns a pointer to the C array. With the SE-0044 Import as member feature this can made to look like a Swift property.
You only have to add the following code either in the C header file where the logging structure is defined, or in the bridging header file:
// Pointer to the data elements:
__attribute__((swift_name("getter:logging.dataPtr(self:)")))
static inline const uint8_t * _Nonnull loggingDataPtr(const logging * _Nonnull log)
{
return log->data;
}
Now you can read the log data in the Swift code via the pointer:
struct ReadLog {
var log = logging()
func read() {
//...Do some stuff...
let char = log.dataPtr[0]
}
}
But be aware that there is no array bounds checking, you must ensure that log.dataPtr is only used with indices within the array size.
If you want to read and write to the logging structure from Swift then change the helper function to
// Pointer to the data elements:
__attribute__((swift_name("getter:logging.dataPtr(self:)")))
static inline uint8_t * _Nonnull loggingDataPtr(logging * _Nonnull log)
{
return log->data;
}
Related
Assume I have an array of structs like so:
struct Record {
let name: String
}
let array = [Record(name: "John"), Record(name: "Jim"), Record(name: "Bob")]
I would like to get the index of each element using UILocalizedIndexedCollation.section(for: collationStringSelector:). The problem is, when I pass:
#selector(getter: record.name)
the following error is returned:
Argument of '#selector' refers to var 'name' that is not exposed to
Objective-C
Is there any way of exposing an instance value in a struct to a #selector? (NB: the struct I am passing is used extensively throughout my app and I don't really want to change it to a class)
Converting the struct variable to an NSString and using one of NSString's methods / variables is a work around that fixed the issue:
let index = UILocalizedIndexedCollation.current().section(for: (record.name as NSString), collationStringSelector: #selector(getter: NSString.uppercased))
I have two structs in a library I cannot change. p.e:
struct{
uint8_t test;
uint8_t data[8];
}typedef aStruct;
struct{
uint8_t value;
uint8_t unimportant_stuff;
char data[8];
}typedef bStruct;
aStruct a;
bStruct b;
In my application there is a process that permantently refreshs my aStruct's.
Now I have a buffer of bStruct's I want to keep updated as well.
The data[] array is the important field. I don't really care about the other values of the structs.
I already made sure, that on that specific system where the code runs on, a "char" is 8Bits as well.
Now I'd like to make the "b.data" array point to exactly the same values as my "a.data" array. So if the process refreshs my aStruct, the values in my bStruct are up to date as well.
Therefore that in C an array is only a pointer to the first element, I thought something like this must be possible:
b.data = a.data
But unfortunately this gives me the compiler-error:
error: assignment to expression with array type
Is there a way to do what I intend to do?
Thanks in advance
Okay, according to the input I got from you guys, I think it might be the best thing to redesign my application.
So instead of a buffer of bStruct's I might use a buffer of aStruct*. This makes sure my buffer is always up to date. And then if I need to do something with an element of the buffer, I will write a short getter-function which copies the data from that aStruct* into a temporary bStruct and returns it.
Thanks for your responses and comments.
If you want b.data[] array to point to exactly the same values, then you can make data of b a char* and make it point to a's data.
Something like
struct{
uint8_t value;
uint8_t unimportant_stuff;
char* data;
}typedef bStruct;
and
b.data = a.data;
But, keep in mind, this means that b.data is pointing at the same memory location as a.data and hence, changing values of b.data would change values of a.data also.
There is another way of doing this. It is by copying all the values of a.data into b.data. Then, b.data would merely contain the same values as a.data, but it would point to different memory locations.
This can either be done by copying one by one. In a for loop for all the 8 elements.
Or, to use memcpy()
NOTE
Arrays cannot be made to point to another memory locations. As they are non modifiable l-value. If you cannot modify the structs, then you have to use the second method.
What you are asking is not possible when you can not modify the existing struct definitions. But you can still automate the functionality with a bit of OO style programming on your side. All of the following assumes that the data fields in the structs are of same length and contain elements of same size, as in your example.
Basically, you wrap the existing structs with your own container. You can put this in a header file:
/* Forward declaration of the wrapper type */
typedef struct s_wrapperStruct wrapperStruct;
/* Function pointer type for an updater function */
typedef void (*STRUCT_UPDATE_FPTR)(wrapperStruct* w, aStruct* src);
/* Definition of the wrapper type */
struct s_wrapperStruct
{
STRUCT_UPDATE_FPTR update;
aStruct* ap;
bStruct* bp;
};
Then you can can create a factory style module that you use to create your synced struct pairs and avoid exposing your synchronization logic to uninterested parties. Implement a couple of simple functions.
/* The updater function */
static void updateStructs(wrapperStruct* w, aStruct* src)
{
if ( (w != NULL) && (src != NULL) )
{
/* Copy the source data to your aStruct (or just the data field) */
memcpy(w->ap, src, sizeof(aStruct));
/* Sync a's data field to b */
sync(w); /* Keep this as a separate function so you can make it optional */
}
}
/* Sync the data fields of the two separate structs */
static void sync(wrapperStruct* w)
{
if (w != NULL)
{
memcpy(w->bp->data, w->ap->data, sizeof(w->bp->data));
}
}
Then in your factory function you can create the wrapped pairs.
/* Create a wrapper */
wrapperStruct syncedPair = { &updateStructs, &someA, &someB };
You can then pass the pair where you need it, e.g. the process that is updating your aStruct, and use it like this:
/* Pass new data to the synced pair */
syncedPair.update( &syncedPair, &newDataSource );
Because C is not designed as an OO language, it does not have a this pointer and you need to pass around the explicit wrapper pointer. Essentially this is what happens behind the scenes in C++ where the compiler saves you the extra trouble.
If you need to sync a single aStruct to multiple bStructs, it should be quite simple to change the bp pointer to a pointer-to-array and modify the rest accordingly.
This might look like an overly complicated solution, but when you implement the logic once, it will likely save you from some manual labor in maintenance.
I am currently working on an embedded system and I have a component on a board which appears two times. I would like to have one .c and one .h file for the component.
I have the following code:
typedef struct {
uint32_t pin_reset;
uint32_t pin_drdy;
uint32_t pin_start;
volatile avr32_spi_t *spi_module;
uint8_t cs_id;
} ads1248_options_t;
Those are all hardware settings. I create two instances of this struct (one for each part).
Now I need to keep an array of values in the background. E.g. I can read values from that device every second and I want to keep the last 100 values. I would like this data to be non-accessible from the "outside" of my component (only through special functions in my component).
I am unsure on how to proceed here. Do I really need to make the array part of my struct? What I thought of would be to do the following:
int32_t *adc_values; // <-- Add this to struct
int32_t *adc_value_buffer = malloc(sizeof(int32_t) * 100); // <-- Call in initialize function, this will never be freed on purpose
Yet, I will then be able to access my int32_t pointer from everywhere in my code (also from outside my component) which I do not like.
Is this the only way to do it? Do you know of a better way?
Thanks.
For the specific case of writing hardware drivers for a microcontroller, which this appears to be, please consider doing like this.
Otherwise, use opaque/incomplete type. You'd be surprised to learn how shockingly few C programmers there are who know how to actually implement 100% private encapsulation of custom types. This is why there's some persistent myth about C lacking the OO feature known as private encapsulation. This myth originates from lack of C knowledge and nothing else.
This is how it goes:
ads1248.h
typedef struct ads1248_options_t ads1248_options_t; // incomplete/opaque type
ads1248_options_t* ads1248_init (parameters); // a "constructor"
void ads1248_destroy (ads1248_options_t* ads); // a "destructor"
ads1248.c
#include "ads1248.h"
struct ads1248_options_t {
uint32_t pin_reset;
uint32_t pin_drdy;
uint32_t pin_start;
volatile avr32_spi_t *spi_module;
uint8_t cs_id;
};
ads1248_options_t* ads1248_init (parameters)
{
ads1248_options_t* ads = malloc(sizeof(ads1248_options_t));
// do things with ads based on parameters
return ads;
}
void ads1248_destroy (ads1248_options_t* ads)
{
free(ads);
}
main.c
#include "ads1248.h"
int main()
{
ads1248_options_t* ads = ads1248_init(parameters);
...
ads1248_destroy(ads);
}
Now the code in main cannot access any of the struct members, all members are 100% private. It can only create a pointer to a struct object, not an instance of it. Works exactly like abstract base classes in C++, if you are familiar with that. The only difference is that you'll have to call the init/destroy functions manually, rather than using true constructors/destructors.
It's common that structures in C are defined completely in the header, although they're totally opaque (FILE, for example), or only have some of their fields specified in the documentation.
C lacks private to prevent accidental access, but I consider this a minor problem: If a field isn't mentioned in the spec, why should someone try to access it? Have you ever accidentally accessed a member of a FILE? (It's probably better not to do things like having a published member foo and a non-published fooo which can easily be accessed by a small typo.) Some use conventions like giving them "unusual" names, for example, having a trailing underscore on private members.
Another way is the PIMPL idiom: Forward-declare the structure as an incomplete type and provide the complete declaration in the implementation file only. This may complicate debugging, and may have performance penalties due to less possibilities for inlining and an additional indirection, though this may be solvable with link-time optimization. A combination of both is also possible, declaring the public fields in the header along with a pointer to an incomplete structure type holding the private fields.
I would like this data to be non-accessible from the "outside" of my
component (only through special functions in my component).
You can do it in this way (a big malloc including the data):
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef struct {
uint32_t pin_reset;
uint32_t pin_drdy;
uint32_t pin_start;
volatile avr32_spi_t *spi_module;
uint8_t cs_id;
} ads1248_options_t;
void fn(ads1248_options_t *x)
{
int32_t *values = (int32_t *)(x + 1);
/* values are not accesible via a member of the struct */
values[0] = 10;
printf("%d\n", values[0]);
}
int main(void)
{
ads1248_options_t *x = malloc(sizeof(*x) + (sizeof(int32_t) * 100));
fn(x);
free(x);
return 0;
}
You could make a portion of your structure private like this.
object.h
struct object_public {
uint32_t public_item1;
uint32_t public_item2;
};
object.c
struct object {
struct object_public public;
uint32_t private_item1;
uint32_t *private_ptr;
}
A pointer to an object can be cast to a pointer to object_public because object_public is the first item in struct object. So the code outside of object.c will reference the object through a pointer to object_public. While the code within object.c references the object through a pointer to object. Only the code within object.c will know about the private members.
The program should not define or allocate an instance object_public because that instance won't have the private stuff appended to it.
The technique of including a struct as the first item in another struct is really a way for implementing single inheritance in C. I don't recall ever using it like this for encapsulation. But I thought I would throw the idea out there.
You can:
Make your whole ads1248_options_t an opaque type (as already discussed in other answers)
Make just the adc_values member an opaque type, like:
// in the header(.h)
typedef struct adc_values adc_values_t;
// in the code (.c)
struct adc_values {
int32_t *values;
};
Have a static array of array of values "parallel" to your ads1248_options_t and provide functions to access them. Like:
// in the header (.h)
int32_t get_adc_value(int id, int value_idx);
// in the code (.c)
static int32_t values[MAX_ADS][MAX_VALUES];
// or
static int32_t *values[MAX_ADS]; // malloc()-ate members somewhere
int32_t get_adc_value(int id, int value_idx) {
return values[id][value_idx]
}
If the user doesn't know the index to use, keep an index (id) in your ads1248_options_t.
Instead of a static array, you may provide some other way of allocating the value arrays "in parallel", but, again, need a way to identify which array belongs to which ADC, where its id is the simplest solution.
NOTE: I've re written the original question to make it much more clear.
I have a function called
VcStatus readVcard( FILE *const vcf, Vcard **const cardp )
vcf is an open file I will read, and cardp is a pointer to the start of an array of cards.
a file will have multiple cards in it.
readVCard reads the file a line at a time, and calls the function parseVcProp to indentify keywords in the line, and assign them to the appropriate place in a structure.
Here are the structures
typedef struct { // property (=contentline)
VcPname name; // property name
// storage for 0-2 parameters (NULL if not present)
char *partype; // TYPE=string
char *parval; // VALUE=string
char *value; // property value string
void *hook; // reserved for pointer to parsed data structure
} VcProp;
typedef struct { // single card
int nprops; // no. of properties
VcProp prop[]; // array of properties
} Vcard;
typedef struct { // vCard file
int ncards; // no. of cards in file
Vcard **cardp; // pointer to array of card pointers
} VcFile;
So a file contains multiple cards, a card contains multiple properties, etc.
The thing is, a single card can any have number of properties. It is not known how many until you are done reading them.
Here is what I do not understand.
How must I allocate the memory to use parseVcProp properly?
Each time I call parseVcProp, i obviously want it to be storing the data in a new structure, so how do i allocate this memory before hand? Do i just malloc(sizeof(VcProp)*1)?
Vcard *getcards(int n) {
Vcard *c = malloc(sizeof(Vcard) + sizeof(VcProp) * n);
c->nprops = n;
return c;
}
You really need to show us the particular line that's producing the error.
With that said, for a structure like vcard that contains a flexible array member, you cannot create variables of that type. You can only create pointer variables. For instance:
vcard *vc = malloc(sizeof(vcard) + n*sizeof(VcProp));
At this point, vc->prop[0] through vc->prop[n-1] are valid array elements (each has type VcProp).
Note that a flexible array member is an array, not a pointer.
Sorry for the confusion everyone.
I figured out my error.
The reason things were going wacky is because propp is an output pointer, not a input pointer
I was trying to use Vcard->prop as a passing argument, when I actually had to just create my own, and send the address of it.
gcc 4.4.1 c89
I have 2 different structures called origin_t and session_t.
I would to pass the instance of one of these structure to my function. However, before I can perform an operation on these I need to cast it to the correct type. My problem is that I don't know how to check for the correct type. Is there any standard c function that can check for the correct instance of this structure.
Many thanks for any advice,
const char* get_value(void *obj)
{
/* Cast to the correct structure type */
if(obj == origin) {
/* Is a origin structure */
origin_t *origin = (origin_t*)obj;
}
else if(obj == session) {
/* Is a session structure */
session_t *session = (session_t*)obj;
}
}
Is there any way to modify the types? Seems like the easiest way it to put a small member that indicates the type if there's no other way to tell.
C doesn't have any built-in runtime type information capabilities, so you'd have to create your own - for example, by putting at the beginning of both origin_t and session_t some integer or pointer to some data structure that would allow you to distinguish between them.
The best way would be to combine the types (if possible!) under a common type such as:
typedef enum {
t_origin,
t_session
} type_t;
struct base_t {
type_t type;
union {
origin_t origin;
session_t session;
};
}
and then:
const char* get_value(base_t *obj)
{
/* Cast to the correct structure type */
if(obj->type == t_origin) {
/* Is a origin structure */
origin_t *origin = &obj->origin;
}
else if(obj->type == t_session) {
/* Is a session structure */
session_t *session = &obj->session;
}
}
There are no ways of determining types from a pointer in C. You have to add your own type mechanism. This is one way to do it without being intrusive in the subtypes (origin_t and session_t). You also don't have to do weird casts, and compromise the already weak type system in the C language.