COpaquePointer to an arbitrary byte in a block of memory - c

I'm porting some code to Swift, but I'm confused about how to handle pointers.
In Swift, how do you create an empty block of memory, in such a manner that C functions can access it?
C source:
UInt8* bytes = malloc( qty_bytes_in_file );
..and, after so-doing, how would you create a pointer to an arbitrary offset of that memory? I'll need to repeatedly move the pointers to various addresses in this block of memory, to which a C function will then write data.
C source:
void* mData = &bytes[i];
Here's an abbreviated version of the C code with which I'm starting, so you can see both lines in context:
C source:
UInt8* bytes = malloc( qty_bytes_in_file ); // Swift equivalent?
while ( !err ) {
AudioBufferList buffer_list = new_buffer_list();
buffer_list.mBuffers[0].mData = &bytes[i]; // Swift equivalent?
// each iteration, ExtAudioFileRead fills
// in a portion of buffer_list's '.mData':
err = ExtAudioFileRead(
audio_file,
&qty_frames_requested,
&buffer_list
);
i += foo;
}

For the first question I would just make an array of byte values:
var bytes = Array<UInt8>(count: qty_bytes_in_file, repeatedValue: 0)
And I think you can provide a reference to that array as an in-out parameter. For example:
let stream = NSInputStream(data: someNSDataObject)
let numberOfBytesRead = stream.read(&bytes, maxLength:buffer.count)
There is also in Swift a wrapper available …
struct UnsafePointer<T>
… with a "memory" property to get to the raw underlying memory.

Related

Cannot convert value of type 'UnsafePointer<UnsafeMutablePointer<Float>>?' to expected argument type 'UnsafePointer<Float>?'

I'm using a C api in Swift. I need to pass audio for which I'm using floatChannelData from AVAudioPCMBuffer.
let audioFile = try! AVAudioFile(forReading: fileURL as URL)
let audioFormat = audioFile.processingFormat
let audioFrameCount = UInt32(audioFile.length)
let audioFileBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: audioFrameCount)
if whisper_full(ctx, wparams, audioFileBuffer?.floatChannelData , Int32(audioFrameCount)) != 0 {
print("failed to process audio")
return
}
C Header:
WHISPER_API int whisper_full(
struct whisper_context * ctx,
struct whisper_full_params params,
const float * samples,
int n_samples);
I tried just using UnsafePointer(audioFileBuffer?.floatChannelData) but that gives a different error. I'm a bit confused about how pointers work in Swift.
I've read the Apple UnsafePointer docs but don't feel any wiser. https://developer.apple.com/documentation/swift/unsafepointer
As stated in Apple floatChannelData documentation, floatChannelDatais a pointer to a list of pointers to frames, a frame being a list of frameLength floats (hence the pointer to a pointer to float).
On the other side, whisper_full() function seems to take directly a pointer to the complete list of floats.
I do not know what whisper_full() does, so if it is suitable, you can call it once for each frame, else you will have to perform some operation to put all the frames one after each other in the memory (an operation that can lead to heavy CPU and memory load), and pass the pointer to the first to your C function.

Encode/decode strings inside byte type in nanopb with C

I have a .proto file that looks like this:
message ObjValue
{
// ...
optional bytes byteval = 6 [max_size = 256]; // arbitrary structure or message
// ...
I use this proto encoding to send structs that change. This struct basically contains ints and strings (a null-terminated char array).
The sender sends the struct doing something like this:
// Here I create the struct and fill it with integers and strings
struct flow_msg *flow_msg = malloc(sizeof(struct flow_msg));
flow_msg->dst_addr = 1;
flow_msg->src_addr = 2;
flow_msg->src_ap_name = strdup(src_ap_name);
// Here I save the length of the struct and a void pointer that points to the struct
struct ser_obj_value *obj_value = malloc(sizeof(struct ser_obj_value));
obj_value->size = sizeof(struct flow_msg) + strlen(src_ap_name) + 1; // +1 because of '\0'
obj_value->data = flow_msg;
Then, the receiver gets the message, decodes it using nanopb and then:
int
handle_msg(void *f_msg)
{
struct flow_msg *flow_msg = (struct flow_msg *)f_msg;
}
At that point, if I try to read the value of an integer there's no problem (flow_msg->dst_addr, for example), but if I want to read the string value, I get a null pointer because the flow_msg->src_ap_name is empty.
I'm lost in terms of how I should properly encode/decode the string value... Really don't know what I'm missing here... Any clues?
First, I realize now how silly my question was. Actually, I'm not deleting it because #jpa took some time to try to answer my doubts.
Mainly the problem was that I was trying to send pointers (i.e., memory addresses) and then the receiver of course did not know what to do with this random memory address. Also, the problem was that I was "unlucky" that probably because I was using the same machine and same compiler in the receiver side some pointers were actually properly dereferenced, and that confused me a lot.

Unable to read data from fixed size C array in Swift with out of bounds data

I am working with a library written in C, Firebird, in my Swift project.
I have a fixed size C array, of size 1, in a struct
typedef struct
{
...
ISC_SHORT sqln /* number of fields allocated */
ISC_SHORT sqld; /* actual number of fields */
XSQLVAR sqlvar[1]; /* first field address */
} XSQLDA;
Imported in Swift as a tuple
public struct XSQLDA {
...
public var sqln: ISC_SHORT /* number of fields allocated */
public var sqld: ISC_SHORT /* actual number of fields */
public var sqlvar: (XSQLVAR) /* first field address */
}
The purpose of my code is to retrieve data describing a statement. For the statement SELECT foo, bar FROM MY_TABLE;, XSQLDA sqlvar array will contains two XSQLVAR, with description of the foo column and bar column.
In C, the struct needs an allocated size of sizeof (XSQLDA) + (n - 1) * sizeof (XSQLVAR), as defined in the following macro in the library header
#define XSQLDA_LENGTH(n) (sizeof (XSQLDA) + (n - 1) * sizeof (XSQLVAR))
Creating a XSQLDA struct in Swift
let pointer = UnsafeMutableRawPointer.allocate(
byteCount: MemoryLayout<XSQLDA>.stride + (Int(n) - 1) * MemoryLayout<XSQLVAR>.stride,
alignment: MemoryLayout<XSQLVAR>.alignment)
var xsqldaPointer = pointer.bindMemory(to: XSQLDA.self, capacity: 1)
Passing this pointer to this struct to a C function of the library
isc_dsql_describe(&self.status, &self.statement, 1, xsqldaPointer);
This function will populate the sqlvar array of XSQLDA structure.
After this call, I iterate over the elements in the array
var sqlVariable: XSQLVAR = .init()
for i in 0...Int(xsqldaPointer.pointee.sqld) {
withUnsafePointer(to: &xsqldaPointer.pointee.sqlvar) { ptr in
sqlVariable = ptr.advanced(by: i).pointee
print(String(cString: &sqlVariable.sqlname.0))
}
}
Over the iterations, the address of the ptr, aka sqlvar th element, even advanced, stay the same. It seems that Swift can only access the first one.
Running the same function in C works properly. I looked in the memory with BitSlicer, and there are only one element when I run the Swift code, and n elements with the C code.
According to the documentation, the C code is
for (i=0, var = out_sqlda->sqlvar; i < out_sqlda->sqld; i++, var++)
for (i = 1; i < my_struct_instance->count; i++) {
var = my_struct_instance->arr[i];
}
I think the problem is coming from memory protection from Swift, but not sure. Any idea ?
I don't understand why to declare a fixed size array of size 1, which will contains an unknown number of elements. Why not a pointer ?
The function documentation is there, and a code example of this function is there. I'm aware that the documentation is about Interbase, by embarcadero. I looked the C code examples in the github, and the C API guide referenced by Firebird there
The problem did not come from the for loop, but from the memory allocation.
let pointer = UnsafeMutableRawPointer.allocate(
byteCount: MemoryLayout<XSQLDA>.stride + (Int(n) - 1) * MemoryLayout<XSQLVAR>.stride,
alignment: MemoryLayout<XSQLVAR>.alignment)
var xsqldaPointer = pointer.bindMemory(to: XSQLDA.self, capacity: 1)
The previous code allocate memory bounded to XSQLDA type, but the allocated memory will contain the XSQLVAR variables.
The proper way to allocate a XSQLDA is the following:
let pointer = UnsafeMutableRawPointer
.allocate(byteCount: XSQLDA_LENGTH(numberOfFields), alignment: 1)
.assumingMemoryBound(to: XSQLDA.self)
With the following function:
func XSQLDA_LENGTH(_ numberOfFields: Int16) -> Int {
return MemoryLayout<XSQLDA>.size + Int(numberOfFields - 1) * MemoryLayout<XSQLVAR>.size
}
I have zero Swift knowledge (and my C knowledge is also limited), but the correct approach is likely to define sqlvar as an array, not as a scalar field. The XSQLVAR sqlvar[1] defines an array that defaults to a single value, but when XSQLDA_LENGTH(n) is called with n > 1, it actually defines an array of size n.
If possible, you should make it an array in your Swift tuple, and allocate n XSQLVARs in that array, and make sure that sqln is set to n. Then, after using isc_dsql_prepare, and sqld > sqln, you need to reallocate an XSQLDA with n equal to sqld and use isc_dsql_describe to populate it.
Alternatively, you can forego this and always use a XSQLDA of size 1 on prepare, and instead use isc_dsql_sql_info to 'manually' create appropriately sized XSQLDA descriptors for input and output fields.
This is the approach I take in Jaybird, the Java database driver for Jaybird. There, I either create an XSQLDA with size 1 (to use on prepare), or one with the right number of parameters/fields to manually create the descriptors based on the result of isql_dsql_sql_info, and allocate the necessary memory (that is because the way the Java implementation works actually shadows a native memory structure instead of directly accessing the native memory).

LabVIEW Call Library Function yielding array of strings

I need to interface C code to LabVIEW, and my C function needs to give back a two dimensional array of strings. I would rather not be forced to predetermine the size of the array in advance. So I want to know, what is the right data format to use (handle to array of C string pointers? Handle to array of string handles?), how to properly do the allocation, and whether it is better to use an array parameter or a return type. The dialog provided for Call Library Function Node only supports arrays of numeric types, so I'm a little bit lost on how to structure this.
You need the LabVIEW Code Interface Reference Manual to figure this stuff out.
You are writing a C function that will return a 2D array of strings to LabVIEW. That means you need to be returning LabVIEW's data structure and using LabVIEW's memory allocator. Include "extcode.h" in your C file (ships with LabVIEW). Then create the following C code:
#include "extcode.h"
struct String2DArrayBlock {
int32 dimensionSize1;
int32 dimensionSize2;
LStrHandle stringArray[1]; // Yes, this is intentional. Do not use LStrHandle* because that syntax changes the memory allocation. Old-school C code. LabVIEW's own C++ code has wrappers for managing this with more type safety.
};
typedef String2DArrayBlock** String2DArrayHandle;
MgErr GenerateMyStrings(String2DArrayHandle *ptrToHandle) {
if (!ptrToHandle)
return mgArgErr; // Gotta pass a location for us to allocate.
if (*ptrToHandle) {
// This handle is already allocated. I'm not going to walk you through all the code needed to deallocate.
return mgArgErr;
}
const int32 dimSize1 = ComputeHeight(); // This is your function... whereever your data is coming from.
const int32 dimSize2 = ComputeWidth(); // Same here.
const int32 numberOfElements = dimSize1 * dimSize2;
if (numberOfElements == 0) {
return mgNoErr; // Done. NULL means empty array, and the handle is already NULL.
}
// DSNewHClr allocates the block and flood fills it with all zeros.
*ptrToHandle = (String2DArrayHandle)DSNewHClr(sizeof(String2DArrayBlock) + ((numberOfElements - 1) * sizeof(LStrHandle))); // -1 because the sizeof block has 1 element.
if (!*ptrToHandle)
return mFullErr; // Out of memory
(**ptrToHandle)->dimensionSize1 = dimSize1;
(**ptrToHandle)->dimensionSize2 = dimSize2;
LStrHandle *current = (**ptrToHandle)->stringArray;
for (int32 i = 0; i < numberOfElements; ++i, ++current) {
std::string myCurrentString = GetMyCurrentString(i); // You write this however you look up the individual strings.
if (myCurrentString.empty())
continue; // NULL means empty string
*current = (LStrHandle)DSNewHClr(sizeof(LStr)); // Allocates a zero-length LStrHandle.
if (!*current)
return mFullErr; // The array will be partially filled, but it is in a safe state for early return.
MgErr err = LStrPrintf(*current, (CStr)"%s", myCurrentString.c_str());
if (err)
return err; // The array will be partially filled, but it is in a safe state for early return.
}
return mgNoErr;
}
Compile your code against the LabVIEW run-time engine (lvrt.dll).
In your G code, drop a Call Library Node, add a parameter that is "Adapt to type" and "Pointers to Handles", and wire it with an empty 2D array. And you're done.

Unfathomable C structures

Hello I am experiencing something I really don't understand the principle with structures in C.
One of my structures contains 2 character strings (named 'seq' and 'foldedSeq'). Both these strings (should) have the same dimensions.
However when I try to modify one, the second automatically takes the same modifications at the same specified place of the string.
Here is the interesting chunk of code:
typedef struct MD {
int nb_line;
int nb_colomn;
EM ** matrix;
char * seq; // Initial sequence.
char * foldedSeq;
} MD;
void set_sequences(MD * M, char * seq) {
M->seq = seq;
M->foldedSeq = M->seq; //Purpose: give to foldedSeq the seq dimensions (perhaps it is useless).
printf("seq= %s\tstrlen= %d\nM->seq= %s\nM->foldedSeq= %s\n", seq, strlen(seq), M->seq, M->foldedSeq);
// Up to this point 'seq' = 'foldedSeq'
int i;
for( i = 0; i < strlen(seq); i++) {
M->foldedSeq[i] = '-'; // Original purpose: make 'foldedSeq' string filled with hyphens only.
}
printf("seq= %s\tstrlen= %d\nM->seq= %s\nM->foldedSeq= %s\n", seq, strlen(seq), M->seq, M->foldedSeq);
// Here is the problem: the string 'seq' REALLY IS modified alongside with 'foldedSeq'... WHY? :(
}
Since I wrote "M->foldedSeq[i]" should be modified, why would "M->seq[i]" be modified as well ??
Thank you for reading and providing me explanations, my logic found a dead end here.
M->seq = seq;
M->foldedSeq = M->seq;
is the same as saying
M->seq = seq;
M->foldedSeq = seq;
They are both pointing to the same location in memory. So modifying one is modifying both.
Probably what you want to do instead is malloc a block of memory that is the same length as the other.
M->foldedSeq = calloc(strlen(seq) + 1, sizeof(char));
What you're witnessing is simple pointer aliasing, a basic feature of the C language. Because you explicitly assign both seq and foldedSeq members to point to the same bit of memory, and modifications through one pointer will be witnessed by the other. If that's not what you intended/wanted, you'd need to copy the memory block of seq before assigning it to foldedSeq to keep the two distinct.
Because they both point to the same memory address and when you modify one you are modifying the other.
This assignment: M->foldedSeq = M->seq; is just assigning memory locations, not doing any sort of copy.
If you want to keep them separate, you will have to allocate memory and copy the string into the new memory.
Try either:
M->foldedSeq = strdp(M->seq) if you want to copy the content too.
Or:
M->foldedSeq = malloc(strlen(M->seq) + 1); to just have a new memory space of the same size.
This line:
M->foldedSeq = M->seq;
is setting the foldedSeq pointer to the same value as seq. It is not creating new space and copying the contents of seq to foldedSeq which is maybe where the confusion is. So when you modify either one the other will be modified as well. One possible solution is to use strdup:
M->foldedSeq = strdup( M->seq ) ;

Resources