Converting a C char array into a Matlab String using Matlab Coder - c

I have some code written in Matlab that I am converting into C code using Matlab Coder.
I have written a C function that I want to call from the generated C code. This works, so far so good.
The problem is that one of the parameters to the C function is a char** used to output a string.
I accomplish this by making an opaque char* and using coder.wref to get the char**. But how do I convert the opaque char* to a Matlab string so I can return it from my function?
The code goes something like this:
function [status,out] = cfun()
buf = coder.opaque('char *', 'NULL');
len = coder.opaque('size_t ', 'NULL');
status = 0;
status = coder.ceval('_cfun', coder.wref(buf), coder.wref(len));
out = buf; % How do I convert buf into a Matlab string here??
end
_cfun will write some data to buf and write the length into len.
My current solution, which almost works, is to manually make a char array in Matlab and transfer to data. Like this:
length = cast(len, 'int32');
out = char(zeros(1,length+1));
for i = 1:(length+1)
out(i) = cast(buf(i), 'int32');
end
The C code generated from this makes no sense and loops infinitely, but I can manually update it to work. However this requires a manual update every time I rerun the code generation.
The C code looks like this:
i18 = length + 1L;
copyfrom = (int)i18;
i = 1;
while (i <= copyfrom) {
source_str->data[0] = (signed char)(int)buf;
i = 2;
}
I can update it to work:
i18 = length + 1L;
copyfrom = (int)i18;
i = 1;
while (i <= copyfrom) {
source_str->data[i-1] = (signed char)(int)(buf[i-1]);
i = i+1;
}
So, is there a way to convert the char* + length into a Matlab string? Or is there a better way of doing what I am trying to?

It's a bit wasteful, but you could allocate a MATLAB char array and memcpy the data into it:
mllen = cast(len,'int32'); % or int64
mlbuf = blanks(mllen); % allocate character vector
coder.ceval('memcpy',coder.wref(mlbuf),buf,len);
use(mlbuf);
You may want a +1 or -1 on sizes based upon whether or not len counts a NULL terminator and if you want it.
If you can somehow figure out len before the call to _cfun then you can just pass mlbuf to _cfun and forget the copy.
The generated code is indexing with 0 and producing an infinite loop because as far as Coder is concerned, buf is a 1-by-1 coder.opaque. You would get an index out of bounds error if you generated a MEX file and ran it.

Related

Kotlin. Get string part out of array of bytes

From a bluetooth device I get data in an array of bytes. 20 bytes are reserved for a string the other bytes contain data like short and int values.
The bytes for the string are converted to a string using Charset.UTF_8 (or US_ASCII). The problem is I can not get ride of the part that contains ordinary zero's like in other languages as c, c# and c++. Tried droplast after determining the first zero character. Nothing works. What am I missing.
The piece of code is this:
val bytes = job.characteristic.value
var index = 0;
var tempBytes = ByteArray(30)
while(index < 20) {
if (bytes[index] != 0.toByte())
tempBytes[index] = bytes[index]
else
break
++index
}
val newString = tempBytes.toString(Charsets.ISO_8859_1).dropLast(20 - index)
Log.i("BleDeviceVM", "Received for newString: " + newString)
Outcome in Android Studio is like this:
I/BleDeviceVM:
Received for newString: LEDServer��������������������
instead of:
LEDServer
*Thanks Broot.
Coming from c, c#, some c++ and some Java Kotlin is a bit confusing at first.This piece of code works fine I think:
var position = job.characteristic.value.indexOf(0)
if ((position > 20) || (-1 == position))
position = 20
_deviceID.value = String(job.characteristic.value, 0, position)
You have a bug in dropLast(). Your tempBytes is of size 30, but in dropLast you subtract index from 20, not from 30. This is why it is usually better to use constants or reference the collection size directly:
tempBytes.toString(Charsets.ISO_8859_1).dropLast(tempBytes.size - index)
Also, there is no need to use dropLast() if we need first n items, because take() does exactly this:
tempBytes.toString(Charsets.ISO_8859_1).take(index)
But honestly, your code is pretty overcomplicated. You can achieve a similar effect by replacing your whole code with simply:
val newString = String(bytes, 0, bytes.indexOf(0))
There are some differences comparing to your code, e.g. it searches past index 20 and it requires a null-byte somewhere. Depending on your specific case it may need to be adjusted.

Simulating an appendable array in C...Kinda

I'm trying to write a C code that does what a chunk of python code I have written does.
I tried to keep all its lines simple, but there still turns out to be some stuff I wrote that C cannot do.
My code will take an array of coordinates and replace/add items to that array over time.
For example:
[[[0,1]],[[2,1],[1,14]],[[1,1]]] ==> [[[0,1]],[[2,1],[1,14],[3,2]],[[1,1]]]
or
[[[0,1]],[[2,1],[1,14]],[[1,1]]] ==> [[[0,1]],[[40]],[[1,1]]]
I think this is impossible in C, but how about instead using strings to represent the lists so they can be added to? Like this:
[['0$1$'],['2$1$1$14$'],['1$1$']] ==> [['0$1$'],['2$1$1$14$3$2'],['1$1$']]
and
[['0$1$'],['2$1$1$14$'],['1$1$']] ==> [['0$1$'],['40$'],['1$1$']]
In my code, I know each array in the array is either one or more pairs of numbers or just one number so this method works for me.
Can C do this and if so please provide an example.
If you know that both the length of a string and the number of said strings won't exceed a certain value, you can do this:
char Strings[NUMBER_OF_STRINGS][MAX_STRING_LENGTH + 1]; // for the null terminator
It would then be a good practice to zero all this memory:
for (size_t i = 0; i < NUMBER_OF_STRINGS; i++)
memset(Strings[i], 0, MAX_STRING_LENGTH + 1);
And if you want to append a string, use strcat:
strcat(Strings[i], SourceString);
A safer (though slightly more costly since you need to call strlen which walks the entire string) solution would be:
strncat(Strings[i], SourceString, MAX_STRING_LENGTH - strlen(Strings[i]));

words processing (dynamic array of structs)

//runs through initial values and set them to null and zero;
for(int g =0;g<Arraysize;g++){Array1[g].word="NULL";Array1[g].usage=0;}
//struct
int Arraysize = 100;
struct HeavyWords{
string word;
int usage;
};
//runs through txt file and checks if word has already been stored, if it didn't,
it adds it as the next point in the struct, if it has, it adds to the usage int at that point in my array of structs
while (myfile >> Bookword)
{totalwords++;cout<<Bookword<<endl;
bool foundWord = false;
for(int q = 0;q<counter;q++)
{
if(Array1[q].word == Bookword)
{
Array1[q].usage++;
foundWord = true;
}
}
if(foundWord == false) {
Array1[counter].word = Bookword;
Array1[counter].usage = 1;
counter++;
//cout<<counter<<endl;
}
//double size of array when the counter reaches array size
if(counter==Arraysize)
{
HeavyWords * Array2;
Array2 = new HeavyWords[2*Arraysize];
for (int k= 0;k<Arraysize;k++)
{
Array2[k].word = Array1[k].word;
}
Arraysize = 2*Arraysize;
Arraydouble++;
HeavyWords* cursor = Array1;
Array1 = Array2;
delete [] cursor;
}
}
//I just started programming in C++ so im apologize if this code is an explosion of nonesence.
//here is my code,
//I have been racking my brain as to why it is not correctly storing the usage of each word, but when I run it, it gives me the incorrect amount of times certain words are used
//would really love if someone could tell me where my logic went wrong
Immediate problem - While copying Array1 to Array2 you are not copying the usage.
Solution - copy the usage. A statement such as Array2[k] = Array1[k] would do.
Suggestions:
You are also not breaking out in the first part of the code when you find a match in the Array1 for the word you are looking for. You code would needlessly continue to iterate over the entire array, when e.g. a match would have been found at say 10th index and you could have come out of the for loop.
You are re inventing the wheel. You need an expandable array; C++ STL has one readymade for you - it is called vector.
Also Array/Vector does NOT look to be right choice for what you are trying to do. On each word you are doing a linear search on the Array1. A map from C++ STL would neatly AND efficiently do what you are trying to do. Your code would also be much shorter. You can look up on how to code with maps. If you write some code, I can help further. Or wait; someone here would write out entire code for you :).

Copying specific data from a source buffer to several target buffers

I have a source buffer which i declared using malloc and i have used fread to read into the buffer some data from a big file. Now I want to separate out alternate chunks of data (say 2 bytes each) from this source buffer into two target buffers. This problem can be extrapolated to copying every nth chunk to n number of target buffers. I need help in the form of a sample code for the simplest case of two target buffers. This is what I thought about which I am quite sure isn't the right thing.
int totsamples = 256*2*2;
int *sbuff = malloc(totsamples);
int *tbuff1 = malloc(totsamples/2);
int *tbuff2 = malloc(totsamples/2);
elements = fread(sbuff, 2, 256*2, fs);
for(i = 0; i<256; i++)
{
tbuff1[i] = sbuff[i*2];
tbuff2[i] = sbuff[(i*2) + 1];
}
Maybe this will give you and idea:
for(i = 0; i<256; i++)
{
tbuff1[2*i+0] = sbuff[i*4+0];
tbuff1[2*i+1] = sbuff[i*4+1];
tbuff2[2*i+0] = sbuff[i*4+2];
tbuff2[2*i+1] = sbuff[i*4+3];
}
Note: Above code is wrong with respect to your malloc() parameters, as it is unclear what your totsamples means, so fix something before using...
Another note: If you want longer than 2 items long chunk, it starts to make sense to use memcpy to do the copying.
Suggestion: Use constants instead of magic numbers, such as const int SAMPLES=256;. Also I'm not sure, but it appears you think size of int is 2? Don't, instead use sizeof(int) etc (and size of int is rarely 2, btw).
Hmm... Are you actually trying to optimize things by copying bytes using integers to copy 4 bytes at a time? Don't! "Premature optimization is root of all evil". You may consider that later, after you code works otherwise, but first create a working non-hacky version, and doubly so, if you need to ask how to do even that, like here...

C - Returning the most repeated/occurring string in an array of char pointers

I have almost completed the code for this problem, which I shall state as under:
Given:
Array of length 'n' (say n = 10000) declared as below,
char **records = malloc(10000*sizeof(*records));
Each record[i] is a char pointer and points to a non-empty string.
records[i] = malloc(11);
The strings are of fixed length (10 chars + '\0').
Requirement:
Return the most frequently occurring string in the above array.
But now, I am interested in obtaining a slightly less brutal algorithm than the primitive one which I have currently, which is to sift through the entire array in two for loops :(, storing strings encountered by the two loops in a temporary array of similar size ('n' - in case all are unique strings) for comparison with the next strings. The inner loop iterates from 'outer loop position + 1' to 'n'. At the same time, I have an integer array, of similar size - 'n', for counting repeat occurrences, with each i th element corresponding to the i th (unique) string in the comparison array. Then find the largest integer and use its index in the comparison array to return the most frequently occurring string.
I hope I am clear enough. I am quite ashamed of the algo myself, but it had to be done. I am sure there is a much smarter way to do this in C.
Have a great Sunday,
Cheers!
Without being good at nice algorithms (Google, Wikipedia and Stackoverflow are good enough for me), one solution that comes out at the top of my head is to sort the array, then use a single loop to go through the entries. As long as the current string is the same as the previous, increase a counter for that string. When done you have a "list" of strings and their occurrence, which can then be sorted if needed.
In most languages, the usual approach would be to construct a hashtable, mapping strings to counts. This has O(N) complexity.
For example, in Python (although usually you would use collections.Counter for this, and even this code can be made more concise using more specialised Python knowledge, but I've made it explicit for demonstration).
def most_common(strings):
counts = {}
for s in strings:
if s not in counts:
counts[s] = 0
counts[s] += 1
return max(counts, key=counts.get)
But in C, you don't have a hashtable in the standard library (although in C++ you can use hash_map from the STL), so a sort and scan can be done instead. It's O(N.log(N)) complexity, which is worse than optimal, but quite practical.
Here's some C (actually C99) code that implements this.
int compare_strings(const void*s0, const void*s1) {
return strcmp((const char*)s0, (const char*)s1);
}
const char *most_common(const char **records, size_t n) {
qsort(records, n, sizeof(records[0]), compare_strings);
const char *best = 0; // The most common string found so far.
size_t max = 0; // The longest run found.
size_t run = 0; // The length of the current run.
for (size_t i = 0; i < n; i++) {
if (!compare_strings(records[i], records[i - run])) {
run += 1;
} else {
run = 1;
}
if (run > max) {
best = records[i];
max = run;
}
}
return best;
}

Resources