How can I cast '*anyopaque' to '[]const u8'? - sdl

I'm interacting with the SDL zig bindings
I have a Surface, which contains a pointer to some pixels. In C, this is a void*, in zig it is an *anyopaque
I want to pass this pointer-to-pixels to the UpdateTexture function, which in C accepts a void* and in zig accepts a []const u8
#ptrCast gives me "illegal pointer cast to slice", so what is the correct way to treat an opaque pointer as a slice?

Cast *anyopaque to a many-item pointer first, then make it into a slice. E.g.
var anyopaque_pointer: *anyopaque = ...
var item_count: usize = ...
var result: []const u8 = #ptrCast([*]u8, anyopaque_pointer)[0..item_count];

Related

llvm: cast i8* type value to double type value

I have a char pointer (Type::getInt8PtrTy(Context) ) and trying to convert a value (string in other words) which holds this pointer into double type (Type::getDoubleTy(Context)). The way I tried is:
Value* stringValue = ... // Value which type Type::getInt8PtrTy(Context)
auto doubleValue = CastInst::CreatePointerCast(stringValue, Type::getDoubleTy(Context), Builder.GetInsertBlock());
AllocaInst *alloca = .. //alloc memory for element which type is Type::getDoubleTy(Context)
Builder.CreateStore(doubleValue, alloca);
The problem is when I'm trying to print doubleValue using external C function (printf), looks like that I got the address but not double value. In other words, I want to write code which do the same like C atoi function.
I'm using C++ API.
I would be grateful for the answers.
atoi doesn't simply cast a variable to a different type. It actually converts a string value into an integer by means of some algorithm.
If you want to do the same, you'll have to include a function implementing that algorithm in your bitcode and then use call instruction on your pointer to get the double value.
If you really want to interpret string's data as double, use bitcast to cast the pointer from i8* to double* and then use load instruction.

Array type 'char [n]' and 'uint8 [n]' is not assignable

I'm trying to convert two types of values: char and uint8.
I have a function someFunction(TLabel *label, TEdit *edit). Inside of this function, I have a variable char var[6+1].
What I'm trying to do:
Get an Alphanumeric text (input of TEdit *edit), convert this text and put it inside of the var.
I know that if I call this function and put the *label and the *edit I can get whatever I want, but the problem is the conversion to associate the text of *edit in the var.
An example of my code (inside of the function):
char var[6+1];
label->Text = "Some text";
var = edit->Text;
//I will put var value inside of an another char (like a #define) that is in a struct, but doesn't matter for now
my_struct.valueOfVar = var;
And I have another function, it's the same code but the valueOfVar above is a uint8, and I can't convert it, too:
uint8 valueOfAnotherVar[6+1];
The issue is not with the types of the elements in the arrays, but rather that you simply can't assign one static array to another like this:
char a[7];
uint8 b[7];
a = b; // error
Instead, if you want to copy the values in the arrays, you can use std::copy like this:
std::copy(std::begin(b), std::end(b), std::begin(a));
If you have a dynamic array, you can still use std::copy, but you have to use the size of the array:
std::copy(b, b + N, a);
Make sure that both a and b point to at least N elements, otherwise you'll invoke undefined behavior.
The Text of a TLabel or TEdit is a System::String, which is an alias for System::AnsiString in C++Builder 2007 and earlier, and for System::UnicodeString in C++Builder 2009 and later. You did not say which version you are using, but it makes a big difference in your example.
You can't assign anything directly to a fixed array, like char[7] or uint8[7], by using operator= like you are attempting to do. You will need to instead convert and copy the String data into the allocated memory of the arrays, eg:
char var[6+1] = {};
label->Text = "Some text"; // OK - String has a constructor for 'const char*'
// if using CB2007 or earlier:
strncpy(var, edit->Text.c_str(), 6);
// if using CB2009 or later:
strncpy(var, AnsiString(edit->Text).c_str(), 6);
And then you can use one of these to copy the contents of var into valueOfVar:
memcpy(my_struct.valueOfVar, var, 7);
std::copy(var, var+7, my_struct.valueOfVar);
std::copy_n(var, 7, my_struct.valueOfVar);

Crystal C bindings: return type char*

I have a function with this signature:
const char* get_version();
My declaration is:
fun get_version(): LibC::Char*
And to use it:
version = MyLib.get_version()
puts version # how to convert to String?
How can I manage the return string? Do I have to import also strlen to measure the length of the C string and covert it to Crystal string manually?
You wrap the Char* pointer with String.new(MyLib.version). If you know the string length, you may call String.new(ptr, size) too.
Note that this will copy the data from the pointer, so the C binding may release its pointer without affecting the Crystal String.

Crystal C bindings: argument const unsigned char **

This is a signature of a C function that I'm trying to use (which produces an array of binary data):
long get_output( const unsigned char ** );
And I map it with:
fun output = get_output( UInt8** ): Int32
In C a working example to use it do:
const unsigned char * data;
get_output( &data );
But in Crystal:
data = uninitialized UInt8
MyLib.output( pointerof( pointerof( data ) ) ) # ERR: pointerof of pointerof not allowed
This works:
data = uninitialized UInt8*
MyLib.output(pointerof(data))
Note that the argument you have is UInt8** so you need to declare a variable of type UInt8*.
However, Crystal supports this idiom really nicely, with the out keyword: https://crystal-lang.org/docs/syntax_and_semantics/c_bindings/out.html
MyLib.output(out data)
# use data
This last way is preferred because it's more DRY, you don't have to repeat the type.
Also be careful, long usually maps to Int64. In general there are good aliases under LibC, for example LibC::Char, LibC::Long, etc.

cast from void* to string libwebsocket

I have a small websocket server built with libwebsockets , and I need to receive a string , the problem is that the data received is a *void, but I have trouble to cast it to string .
static int my_protocol_callback(struct libwebsocket_context *context,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
{
int n, m;
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 +
LWS_SEND_BUFFER_POST_PADDING];
unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
switch (reason) {
case LWS_CALLBACK_ESTABLISHED:
printf("New Connection\n");
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
break;
case LWS_CALLBACK_RECEIVE:
webcmd = static_cast<std::string*>(in);
break;
case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
break;
default:
break;
}
return 0;
}
under the LWS CALLBACK RECEIVE case, the data is *in, and I casted it by static_cast<std::string*>(in);, stored in the webcmd string.
the problem is that the result is a char pointer, instead I need a true char because next I need to split the string.
what do you think about it?
EDIT : resolved the problem .
Under case LWS_CALLBACK_RECEIVE:
tmpcmd = reinterpret_cast <char*>(in);
strcpy(webcmd , tmpcmd );
webcmd is a char array
and tmpcmd is a char pointer
thank you for all :D
You can't just static_cast to anything you like and hope that it is going to work. Unfortunately you are allowed without warning to cast a void* to anything you like.
static_cast, like reinterpret_cast just changes the type a compile-time without any checks as to whether what is pointed to by the pointer actually represents the type you are casting it to.
In this case, a std::string is a complex type with multiple member variables and memory representation. And unless you passed in exactly the same type, you will have catastrophic results.
It would be much better to pass in the actual type, rather than void*, but I don't know if that is possible with what you are doing.
If you really need a string then you need to use one of std::strings constructors.
Like this:
case LWS_CALLBACK_RECEIVE:
std::string command(static_cast<char*>(in));
webcmd = command; //I don't know what webcmd is.
break;
"in" should be some char array , you should do something like this:
char * buf = new char[DATA_SIZE];
and then memory copy the data into it as array of characters (or BYTE).
Once something has been cast to a void*, all type information has been lost.
You need to search through the code / documentation that sets up the callback function and convert back to the data type of the instance that was originally cast to the void*. It may well be a std::string*, but could be other types such as a char*. Then, to make your code really clear, use a reinterpret_cast:
whateverthetypeis* = reinterpret_cast<whateverthetypeis*>(in);
These days, callbacks can be modelled as functors or by using templates. Then the type information is preserved. The mechanism you're currently using is a throwback to the old C days when void* was used as a generic type.
As for wanting a true char; you will not get that. A char is just a number between -128 and +127. However a char* (i.e. a char pointer) is used by C and C++ to model a sequence of non-zero characters starting at the memory location denoted by the char*: i.e. a string.
If it turns out that in is a char*, then you can construct a std::string with in as the constructor argument and split the std::string at your leisure.