Create and reference a string literal via LLVM C interface - llvm

I'm trying to create a string literal via LLVM C API, and get a C style pointer to its first member. LLVMBuildGlobalStringPtr does the trick nicely, but I can't use it because my source string might contain nulls.
I cannot seem to find documentation on how to create an initialized, unnamed, constant global string.
I've tried using LLVMConstString to create the string and LLVMConstIntToPtr to get its address (and, then, GetElementPointer to convert to i8*). I can get LLVM to compile it, but the resulting object file does not contain the string, and the code returns a pointer that seems random.

I've found the answer. The following code segment seems to do the trick:
LLVMValueRef defineStringLiteral( const char *sourceString, size_t size ) {
LLVMTypeRef strType = LLVMArrayType( LLVMInt8Type(), size );
LLVMValueRef str = LLVMAddGlobal(module->getLLVMModule(), strType, "");
LLVMSetInitializer(str, LLVMConstString( sourceString, size, true ));
LLVMSetGlobalConstant(str, true);
LLVMSetLinkage(str, LLVMPrivateLinkage);
LLVMSetUnnamedAddress(str, LLVMGlobalUnnamedAddr);
LLVMSetAlignment(str, 1);
LLVMValueRef zeroIndex = LLVMConstInt( LLVMInt64Type(), 0, true );
LLVMValueRef indexes[2] = { zeroIndex, zeroIndex };
LLVMValueRef gep = LLVMBuildInBoundsGEP2(builder, strType, str, indexes, 2, "");
return gep;
}

Related

c++ How do I fix my no instance error on my setMaterial piece of code

I just started coding with C++, and am doing a few tutorials on using C++, but when I finished up one part of code I saw that it was erroring:
no instance of overload function "Unigine::ObjectMeshDynamic""setMaterial" matches the argument
Here is my code, and even though I did exactly as I was supposed to, maybe there was something I missed, even after looking at it over and over again (this is in unigine):
int AppWorldLogic::addMeshToScene(const char *file_name, const char *mesh_name, const char *material_name, Math::Vec3 position)
{
MeshPtr mesh = Mesh::create();
ObjectMeshDynamicPtr omd;
if (file_name)
{
if (!mesh->load(file_name))
{
Log::error("\nError opening .mesh file!\n");
mesh.clear();
return 0;
}
else omd = ObjectMeshDynamic::create(mesh);
}
else
{
mesh->addBoxSurface("box_surface", Math::vec3(0.5f));
omd = ObjectMeshDynamic::create(mesh);
}
// setting node material, name and position
omd->setMaterial(material_name, "*");
omd->setName(mesh_name);
omd->setWorldPosition(position);
Objects.append(omd);
Log::message("-> Object %s added to the scene. \n", mesh_name);
mesh.clear();
return 1;
}
If you read Unigine's current (2.15.1) documentation for setMaterial() (which Unigine::ObjectMeshDynamic inherits from Unigine::Object), you will see that it is overloaded to accept only the following parameters:
void setMaterial ( const Ptr<Material> & mat, int surface )
void setMaterial ( const Ptr<Material> & mat, const char * pattern )
You are trying to call SetMaterial() with 2 strings as input, and there is no such overload available, hence the error.
"*" is a string literal, which is implemented as a const char[2] array that decays into a const char*. So you can safely pass that to the pattern parameter.
However, you are trying to pass your material_name variable, which is a const char* string, to the mat parameter. A const char* is not compatible with Ptr<Material>. setMaterial() wants a pointer to a Unigine::Material object instead of a string.
I looked at earlier versions of the documentation, and found that prior to 2.15, there were additional overloads of setMaterial(), some of which accepted a const char* name parameter instead of a const Ptr<Material> &mat parameter. It seems those overloads where removed in 2.15. Which means the code you are trying to use was meant for an earlier version of Unigine, not for the latest version.
It appears that you copied your code from this documentation page, which has apparently not been updated to account for the latest Unigine version. There is obviously now another step involved to get a Material object from a name string in the latest version. For instance, by calling Materials::findMaterial(). Or alternatively, using setMaterialPath() instead of setMaterial().
Have a look at the Upgrading to UNIGINE 2.15: API Migration: Materials Changes documentation.

Cannot use std::string variable in RapidJSON function call

I am all new to C++ and am running into an issue. I am using rapidJSON to create JSON documents.
void setKeyValue() {
Value obj(kObjectType);
Value key("key");
Value val(42);;
obj.AddMember(key, val, d.GetAllocator());
}
Works as expected. But when I try to replace the call to key to make it use a passed in param, like so:
void setKeyValue(string myKey) {
Value obj(kObjectType);
Value key(myKey);
Value val(42);;
obj.AddMember(key, val, d.GetAllocator());
}
The myKey in Value key(myKey) get a red curly underling in Visual Studio saying the following:
What is causing this and how can I solve it?
You don't get support for std::string by default. rapidJSON requires you to specify you want std::string support.
#define RAPIDJSON_HAS_STDSTRING 1
Only then is this constructor you're using valid:
GenericValue (const std::basic_string< Ch > &s, Allocator &allocator)
JSON library you are using seems that doesn't work with string objects from standard library, but it works with const char*.
So you must convert string object to char* with the method c_str():
void setKeyValue(string myKey) {
Value obj(kObjectType);
Value key((char*)myKey.c_str());
Value val(42);;
obj.AddMember(key, val, d.GetAllocator());
}

C++ nlohmann/json how to use runtime provided json_pointers to read json values

I am using the json parser Json for Modern C++ (https://github.com/nlohmann/json). I know that I can get the value of a JSON value with a JSON_Pointer:
auto v1 = j["/a/b/c"_json_pointer];
But how would I go about getting the value if the JSON Pointer is defined at runtime (passed into my function)?
std:string s1 = "/a/b/c";
auto v1 = j[s1]; // doesn't work
You can't append "json_pointer" to either the std::string assignment or to the s1 variable. Is there a function that will convert a std::string to a json_pointer? The caller knows nothing about json and can't have access to the "json.hpp" header. I've also tried
std::string s1 = "/a/b/c";
json_pointer p1(s1);
but "json_pointer" class is undefined. Other than this issue this is a great library that does everything else I need. TIA.
Look at the source code:
inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t)
{
return nlohmann::json::json_pointer(s);
}
If json_pointer is undefined, then you aren't using the right namespaces. Try
using nlohmann::json::json_pointer;
std::string s1 = "/a/b/c";
json_pointer p1(s1);

How to insert and retrieve QString from sqlite using native sqlite library instead of QSql

I am using native sqlite library (amalgamation 1file) within a C++ project that uses Qt, I created a simple wrapper around it, but I am having troubles inserting and selecting long UTF-8 texts.
I use this code to insert data:
SqlResult *result = new SqlResult();
sqlite3_stmt *statement;
int current_parameter = 1;
this->LastStatement = sql;
int x = sqlite3_prepare_v2(this->db, sql.toUtf8().constData(), sql.length() + 1, &statement, NULL);
foreach (QString text, parameter)
{
////////////// here is problem ///////////////
x = sqlite3_bind_text(statement, current_parameter++, text.toUtf8().constData(), -1, SQLITE_STATIC);
if (!this->Evaluate(x))
...
As you can see I am using SQL variable ? for which text is bound to using function sqlite3_bind_text(statement, current_parameter++, text.toUtf8().constData(), -1, SQLITE_STATIC) which should take value of QString text and turn it into utf8 const char *. However the text that I get in database is partially garbage (when I use some sqlite browser application I can see some weird symbols).
This is code I use to convert const char * which I get from sqlite3_column_text
static QString StringFromUnsignedChar( const unsigned char *str )
{
std::string temp = std::string(reinterpret_cast<const char*>(str));
return QString::fromUtf8(temp.c_str());
}
The text I get is same "garbage" I see in sqlite manager. So I suppose the problem is during insertion and that select probably works. What is wrong? How can I properly use that sqlite3_bind_text function with QString?
P.S. I would prefer not to use Qt's own sqlite implementation of sqlite, mainly for compatibility purposes (on linux I use Qt4 and on windows Qt5 and I would like to have identical sqlite library everywhere for portability)
Problem in my case was with my own code, the usage is correct but implementation not. This line:
sqlite3_bind_text(statement, current_parameter++, text.toUtf8().constData(), -1, SQLITE_STATIC);
needs to be
sqlite3_bind_text(statement, current_parameter++, text.toUtf8().constData(), -1, SQLITE_TRANSIENT);
As documentation states:
The fifth argument to the BLOB and string binding interfaces is a
destructor used to dispose of the BLOB or string after SQLite has
finished with it. The destructor is called to dispose of the BLOB or
string even if the call to bind API fails. If the fifth argument is
the special value SQLITE_STATIC, then SQLite assumes that the
information is in static, unmanaged space and does not need to be
freed. If the fifth argument has the value SQLITE_TRANSIENT, then
SQLite makes its own private copy of the data immediately, before the
sqlite3_bind_*() routine returns.
So the correct way to use QString with sqlite using its native API's is:
// Create and evaluate a statement
sqlite3_stmt *statement;
// Note: return value should be checked for error here
sqlite3_prepare_v2(pointer_to_sqlite_db, sql.toUtf8().constData(), sql.length() + 1, &statement, NULL);
// Bind QString to SQL statement - it must be transient so that sql text persist even after function call is over and data is destructed
sqlite3_bind_text(statement, current_parameter++, text.toUtf8().constData(), -1, SQLITE_TRANSIENT);
// step
sqlite3_step(statement);
// clean up
sqlite3_finalize(statement);
How to convert const char * back to QString
static QString StringFromUnsignedChar( const unsigned char *str )
{
return QString::fromUtf8(reinterpret_cast<const char*>(str));
}
QString result = StringFromUnsignedChar(sqlite3_column_text(statement, column));

How can I bind a C/C++ structure to Ruby?

I need some advice how can I bind a C/C++ structure to Ruby. I've read some manuals and I found out how to bind class methods to a class, but I still don't understand how to bind structure fields and make them accessible in Ruby.
Here is the code I'm using:
myclass = rb_define_class("Myclass", 0);
...
typedef struct nya
{
char const* name;
int age;
} Nya;
Nya* p;
VALUE vnya;
p = (Nya*)(ALLOC(Nya));
p->name = "Masha";
p->age = 24;
vnya = Data_Wrap_Struct(myclass, 0, free, p);
rb_eval_string("def foo( a ) p a end"); // This function should print structure object
rb_funcall(0, rb_intern("foo"), 1, vnya); // Here I call the function and pass the object into it
The Ruby function seems to assume that a is a pointer. It prints the numeric value of the pointer instead of it's real content (i.e., ["Masha", 24]). Obviously the Ruby function can't recognize this object —I didn't set the object's property names and types.
How can I do this? Unfortunately I can't figure it out.
You have already wrapped your pointer in a Ruby object. Now all you have to do is define how it can be accessed from the Ruby world:
/* Feel free to convert this function to a macro */
static Nya * get_nya_from(VALUE value) {
Nya * pointer = 0;
Data_Get_Struct(value, Nya, pointer);
return pointer;
}
VALUE nya_get_name(VALUE self) {
return rb_str_new_cstr(get_nya_from(self)->name);
}
VALUE nya_set_name(VALUE self, VALUE name) {
/* StringValueCStr returns a null-terminated string. I'm not sure if
it will be freed when the name gets swept by the GC, so maybe you
should create a copy of the string and store that instead. */
get_nya_from(self)->name = StringValueCStr(name);
return name;
}
VALUE nya_get_age(VALUE self) {
return INT2FIX(get_nya_from(self)->age);
}
VALUE nya_set_age(VALUE self, VALUE age) {
get_nya_from(self)->age = FIX2INT(age);
return age;
}
void init_Myclass() {
/* Associate these functions with Ruby methods. */
rb_define_method(myclass, "name", nya_get_name, 0);
rb_define_method(myclass, "name=", nya_set_name, 1);
rb_define_method(myclass, "age", nya_get_age, 0);
rb_define_method(myclass, "age=", nya_set_age, 1);
}
Now that you can access the data your structure holds, you can simply define the high level methods in Ruby:
class Myclass
def to_a
[name, age]
end
alias to_ary to_a
def to_s
to_a.join ', '
end
def inspect
to_a.inspect
end
end
For reference: README.EXT
This is not a direct answer to your question about structures, but it is a general solution to the problem of porting C++ classes to Ruby.
You could use SWIG to wrap C/C++ classes, structs and functions. In the case of a structure, it's burning a house to fry an egg. However, if you need a tool to rapidly convert C++ classes to Ruby (and 20 other languages), SWIG might be useful to you.
In your case involving a structure, you just need to create a .i file which includes (in the simplest case) the line #include <your C++ library.h>.
P.S. Once more, it's not a direct answer to your question involving this one struct, but maybe you could make use of a more general solution, in which case this may help you.
Another option is to use RubyInline - it has limited support for converting C and Ruby types (such as int, char * and float) and it also has support for accessing C structurs - see accessor method in the API.