I am trying to make a drawing in openGL using glfw, the problem i'm facing is that to save the various coordinates of the points (i can't know their value or how many there will be in advance) i need to realloc a pointer to get more space to save them.
I need to realloc the pointer only when i press a button, hence i thought it made sense for the realloc to be in the key_callback function.
The problem is that, obviously, int *pointer isn't in the scope of key_callbackso i can't realloc it directly there and i can't pass the int * to key_callback since it's a glfw fucntion that has specific arguments that i can't change.
My question is, should i declare int *pointer = malloc outside of main (globally) so that it's visible from both main and key_callback, increase a global variable inside key_callback and do something like if (new_variable_value != old_variable_value){realloc} inside main or there exist a third alternative that i didn't think of?
This is a skeleton of the code i have now: (obviously it won't work for many reasons, it's just to give you an idea of what i want to do)
key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
// do stuff
// realloc pointer
}
int main(void) {
int *pointer = malloc(sizeof(int));
if (!pointer){
free(pointer);
exit(EXIT_FAILURE);
}
GLFWwindow *window;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(1280, 720, "Example", NULL, NULL);
if (!window) {
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
while (!glfwWindowShouldClose(window)) {
//draw stuff
glfwSwapBuffers(window);
glfwPollEvents();
}
free(pointer);
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
User pointer:
Each window has a user pointer that can be set with glfwSetWindowUserPointer and fetched with glfwGetWindowUserPointer. This can be used for any purpose you need and will not be modified by GLFW throughout the life-time of the window.
The initial value of the pointer is NULL.
Declare pointer as a global variable. This is the simplest possible fix.
You will need to initialize the pointer with malloc() within main() -- variables declared in the global scope can only be initialized to constant values, not function calls.
Related
I have a function called create_interface. In that function is a signal handler for the Open menu button (the menu is created in create_interface). I want to pass the window widget and also pass along the tree view widget, because when you open a file an entry in the tree view is supposed to show up. I tried passing them as a struct, but, although its works, GTK generates some error messages.
// This is global.
struct everything
{
GtkWidget *window;
GtkWidget *tree_view;
}
GtkWidget *create_interface (void)
{
struct everything instance;
struct everything *widgets;
widgets = &instance;
...code here...
g_signal_connect(file_mi_open_file_dialog, "clicked", G_CALLBACK(open_file_dialog), widgets);
The function open_file_dialog looks like this:
void open_file_dialog (GtkWidget *wid, gpointer data)
{
struct everything *sample_name = data;
...rest of code here...
I was wondering if there was another way of organizing a program so you do not have to have global variables.
I tried passing them as a struct, but, although its works, GTK generates some error messages.
The problem is that you're trying to use a stack-allocated struct, which becomes invalid after the create_interface() function is done, while you would normally expect these values to still be valid at a later moment in time (for example, when open_file_dialog() is called.
I was wondering if there was another way of organizing a program so you do not have to have global variables.
One possible solution is indeed to use a global variable: this will be valid throughout the lifetime of the program, but it has major drawbacks: it doesn't scale if you have to do that for each callback, and it's architecturally not really clean.
Another solution is to allocate your "closure" (i.e. the variables you want to capture at the moment you create your callback) on the heap, and to free it when you're done with it. GLib even helps you with this by a call g_signal_connect_data() (or g_signal_connect_object() if you save your fields in a GObject)
// Technically you don't need the typedef
typedef struct _ClickedClosure {
GtkWidget *window;
GtkWidget *treeview;
} ClickedClosure;
GtkWidget *create_interface (void)
{
// Note that the g_new0 allocates on the heap instead of using the stack
ClickedClosure *closure = g_new0 (ClickedClosure, 1);
// code here to initialize your window/treeview ...
// put the widgets in the closure
closure->window = my_window;
closure->treeview = treeview;
// Connect to the signal
g_signal_connect_data(file_mi_open_file_dialog, "clicked",
G_CALLBACK(open_file_dialog), closure, g_free, 0);
}
void open_file_dialog (GtkWidget *wid, gpointer data)
{
// Since this was allocated on the heap, this is still valid
ClickedClosure *sample_name = data;
// code handling here ...
}
Very often, what developers using GTK do, is that they're using their own GObject classes/objects already, which they can then use with g_signal_connect_object(), or by manually freeing it with g_object_unref() later. Using GObject then also allows you to to a runtime-typecheck cast, which makes sure your closure has the right type.
I am currently developing a Vulkan program that I anticipate to use as a game engine, but I am far from my goal. As a first step, I'm just trying to render a triangle using a list of dynamic structures to get data such as vertices and shaders. To work around platform specific hurdles, I'm using GLFW to create windows and Vulkan surfaces.
Right now I'm trying to load SPIR-V shaders from a file and use them to create VkShaderModules which I will use in my render pipeline. Currently, the abstracted part of my code starts like this:
main.c
#include "application.h"
#include "config.h"
#include "engine_vulkan.h"
#include "glfw/glfw3.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
printf("VLK Engine - Version %s\n", VERSION_NUMBER);
if (enable_validation_layers) {
printf("Validation layers enabled.\n");
}
printf("\n");
struct VulkanData vulkan_data = {0};
struct Application app = {.window = NULL, .vulkan_data = &vulkan_data, .objects = NULL};
bool ret = application_init(&app);
if (ret == false) {
fprintf(stderr, "Cannot initialize applcation.\n");
return EXIT_FAILURE;
}
while (application_loopcondition(&app)) {
application_loopevent(&app);
}
application_close(&app);
return EXIT_SUCCESS;
}
application.c
#include "application.h"
#include "engine_object.h"
#include "engine_vulkan.h"
bool application_init(struct Application *app) {
bool ret;
// Initialize GLFW
glfwInit();
// Create window
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
app->window = glfwCreateWindow(800, 600, "Vulkan window", NULL, NULL);
if (app->window == NULL) {
fprintf(stderr, "Failed to create window.\n");
return false;
}
printf("Created window # 0x%p\n", app->window);
// Initialize game object list
objectlink_init(app);
// Create game objects
struct RenderObjectCreateInfo ro_create_info = {.vertex_shader_path = "shaders/shader.vert.spv",
.fragment_shader_path =
"shaders/shader.frag.spv",
.is_static = true};
struct RenderObject triangle = {0};
object_init(app, &ro_create_info, &triangle);
objectlink_add(app, &triangle);
// Init Vulkan
ret = vulkan_init(app);
if (!ret) {
fprintf(stderr, "Failed to initialize Vulkan.\n");
return false;
}
return true;
}
bool application_loopcondition(struct Application *app) {
// Close only if GLFW says so
return !glfwWindowShouldClose(app->window);
}
void application_loopevent(struct Application *app) {
// Poll for events like keyboard & mouse
glfwPollEvents();
}
void application_close(struct Application *app) {
// Destroy objects
objectlink_destroy(app);
// Close Vulkan instance
vulkan_close(app);
// End window & GLFW
glfwDestroyWindow(app->window);
glfwTerminate();
}
Important structures
struct Application {
GLFWwindow *window;
struct VulkanData *vulkan_data;
struct RenderObjectLink *objects;
};
struct RenderObject {
char *vertex_shader_path;
struct ShaderFile vertex_shader_data;
VkShaderModule vertex_shader;
char *fragment_shader_path;
struct ShaderFile fragment_shader_data;
VkShaderModule fragment_shader;
bool is_static;
};
struct RenderObjectCreateInfo {
char *vertex_shader_path;
char *fragment_shader_path;
bool is_static;
};
struct RenderObjectLink {
struct RenderObject *render_object;
struct RenderObjectLink *next;
};
The problem in my application comes when storing the VkShaderModules in my application structure. The way that my program is supposed to store information about objects is in the Application structure called app, in which it points to a linked list of RenderObjectLink in the objects field. My functions objectlink_init and objectlink_add work properly, however the data inside the structure the render_object field points to gets changed/corrupted when entering the GLFW functions glfwWindowShouldClose and glfwPollEvents.
Since those two functions are ran after initializing Vulkan and creating the shader modules, I've found with GDB that the Vulkan functions are working properly and that my data structures are only getting corrupted when running the GLFW loop functions. I have debugged with GDB using hardware watch points to determine that the reference to these shaders (among other variables throughout the program) changes upon entering these functions.
Thread 1 hit Hardware watchpoint 4: app->objects->render_object->vertex_shader
Old value = (VkShaderModule) 0x731f0f000000000a
New value = (VkShaderModule) 0x40d625 <glfwPollEvents+43>
_glfwPlatformPollEvents () at C:/Users/dylanweber/Documents/C-Projects/vlkengine/main/glfw/src/win32_window.c:1878
1878 {
This happens consistently but the variable changes to different values when I run it. Memory analysis tools like Dr. Memory (since I'm using Windows I cannot use Valgrind) only show memory problems in system DLLs (like xinput reading for controller inputs through GLFW) and are unrelated to my program. What could be the cause of this corruption? What tools/resources can I use to find these issues?
According to the code, the objectlink_add function accepts the second argument as a pointer. The most likely use of this is to add the pointer to an underlying data struct and keep it around for further references. A render pipeline was mentioned in the post, which wold be a sort of link.
However, the function was called from the application_init procedure which has the object triangle allocated on its stack. By the time the function is returned, its stack is gone and the value at the pointer becomes invalid.
There are several ways to fix it:
To allocate the triangle struct dynamically, using malloc (or similar). Therefore it will no disappear after the return from the function. This is the most generic way, but it calling to the free() function at some time is expected.
The triangle object could be static.
the objectlink_add could copy triangle fields in some internal struct, however, if there are multiple types of the objects, it cold be problematic.
I would like to create a wrapper for c functions, so that I can convert a function call of the form ret = function(arg1,arg2,arg3); into the form /*void*/ function_wrapper(/*void*/);. That is similar to function objects in C++ and boost bind.
Is this possible? how can I do it?
Update:
To explain in more details what I am looking for:
We start with this function:
int f(int i){
//do stuff
return somevalue;
}
Obvioulsy, it is called like this:
// do stuff
int x = 0;
ret = f(0);
// do more stuff.
I would like to do some magic that will wrap the function into void function(void)
struct function_object fo;
fo.function_pointer = &f;
fo.add_arg(x, int);
fo.set_ret_pointer(&ret);
fo.call();
Note: I saw that there was a vote for closing this question and marking it as unclear. Please do not do that. I have a legitimate need to get this question answered. If you need explanation, ask and I will be glad to elaborate.
I came up with a better code that might allow you to do what you want. First I'll explain how it works, show the code and explain why I still don't think it's a good idea to use it (though the code might open doors for improvements that addresses those issues).
Functionality:
Before you start using the "function objects", you have to call an initialization function (FUNCTIONOBJ_initialize();), which will initialize the mutexes on every data structure used in the library.
After initializing, every time you want to call one of those "function objects", without using the parameters, you will have to set it up first. This is done by creating a FUNCTIONOBJ_handler_t pointer and calling get_function_handler(). This will search for a free FUNCTIONOBJ_handler data structure that can be used at the moment.
If none is found (all FUNCTIONOBJ_handler data structures are busy, being used by some function call) NULL is returned.
If get_function_handler() does find a FUNCTIONOBJ_handler data structure it will try to lock the FUNCTIONOBJ_id_holder data structure, that holds the ID of the FUNCTIONOBJ_handler of the function about to be called.
If FUNCTIONOBJ_id_holder is locked already, get_function_handler() will hang until it's unlocked by the thread using it.
Once FUNCTIONOBJ_id_holder is locked, the ID of the grabbed FUNCTIONOBJ_handler is wrote on it and the FUNCTIONOBJ_handler pointer is returned by get_function_handler.
With the pointer in hand, the user can set the pointer to the arguments and the return variable with set_args_pointer and set_return_pointer, which both take a void * as arguments.
Finally, you can call the function you want. It has to:
1 - Grab the FUNCTIONOBJ_handler ID from the FUNCTIONOBJ_id_holder data structure and use it to get a pointer to the FUNCTIONOBJ_handler itself.
2 - Use the FUNCTIONOBJ_handler to access the arguments.
3 - Return by using one of the return function (on the example we have ret_int, which will return an integer and unlock the FUNCTIONOBJ_handler)
Below is a simplified mind map describing a bit of what is going on:
Finally, the code:
funcobj.h:
#include <stdio.h>
#include <pthread.h>
#define MAX_SIMULTANEOUS_CALLS 1024
typedef struct {
//Current ID about to be called
int current_id;
//Mutex
pthread_mutex_t id_holder_mutex;
} FUNCTIONOBJ_id_holder_t;
typedef struct {
//Attributes
void *arguments;
void *return_pointer;
//Mutex
pthread_mutex_t handler_mutex;
} FUNCTIONOBJ_handler_t;
FUNCTIONOBJ_handler_t FUNCTIONOBJ_handler[MAX_SIMULTANEOUS_CALLS];
FUNCTIONOBJ_id_holder_t FUNCTIONOBJ_id_holder;
void set_return_pointer(FUNCTIONOBJ_handler_t *this, void *pointer);
void set_args_pointer(FUNCTIONOBJ_handler_t *this, void *pointer);
void ret_int(FUNCTIONOBJ_handler_t *this, int return_value);
void FUNCTIONOBJ_initialize(void);
FUNCTIONOBJ_handler_t *get_function_handler(void);
funcobj.c:
#include "funcobj.h"
void set_return_pointer(FUNCTIONOBJ_handler_t *this, void *pointer){
this->return_pointer = pointer;
}
void set_args_pointer(FUNCTIONOBJ_handler_t *this, void *pointer){
this->arguments = pointer;
}
void ret_int(FUNCTIONOBJ_handler_t *this, int return_value){
if(this->return_pointer){
*((int *) (this->return_pointer)) = return_value;
}
pthread_mutex_unlock(&(this->handler_mutex));
}
void FUNCTIONOBJ_initialize(void){
for(int i = 0; i < MAX_SIMULTANEOUS_CALLS; ++i){
pthread_mutex_init(&FUNCTIONOBJ_handler[i].handler_mutex, NULL);
}
pthread_mutex_init(&FUNCTIONOBJ_id_holder.id_holder_mutex, NULL);
}
FUNCTIONOBJ_handler_t *get_function_handler(void){
int i = 0;
while((0 != pthread_mutex_trylock(&FUNCTIONOBJ_handler[i].handler_mutex)) && (i < MAX_SIMULTANEOUS_CALLS)){
++i;
}
if(i >= MAX_SIMULTANEOUS_CALLS){
return NULL;
}
//Sets the ID holder to hold this ID until the function is called
pthread_mutex_lock(&FUNCTIONOBJ_id_holder.id_holder_mutex);
FUNCTIONOBJ_id_holder.current_id = i;
return &FUNCTIONOBJ_handler[i];
}
main.c:
#include "funcobj.h"
#include <string.h>
//Function:
void print(void){
//First the function must grab the handler that contains all its attributes:
//The FUNCTIONOBJ_id_holder is mutex locked, so we can just access its value and
//then free the lock:
FUNCTIONOBJ_handler_t *this = &FUNCTIONOBJ_handler[FUNCTIONOBJ_id_holder.current_id];
//We dont need the id_holder anymore, free it!
pthread_mutex_unlock(&FUNCTIONOBJ_id_holder.id_holder_mutex);
//Do whatever the function has to do
printf("%s\n", (char *) this->arguments);
//Return the value to the pointed variable using the function that returns an int
ret_int(this, 0);
}
void *thread_entry_point(void *data){
int id = (int) data;
char string[100];
snprintf(string, 100, "Thread %u", id);
int return_val;
FUNCTIONOBJ_handler_t *this;
for(int i = 0; i < 200; ++i){
do {
this = get_function_handler();
} while(NULL == this);
set_args_pointer(this, string);
set_return_pointer(this, &return_val);
print();
}
return NULL;
}
int main(int argc, char **argv){
//Initialize global data strucutres (set up mutexes)
FUNCTIONOBJ_initialize();
//testing with 20 threads
pthread_t thread_id[20];
for(int i = 0; i < 20; ++i){
pthread_create(&thread_id[i], NULL, &thread_entry_point, (void *) i);
}
for(int i = 0; i < 20; ++i){
pthread_join(thread_id[i], NULL);
}
return 0;
}
To compile: gcc -o program main.c funcobj.c -lpthread
Reasons to avoid it:
By using this, you are limiting the number of "function objects" that can be running simultaneously. That's because we need to use global data structures to hold the information required by the functions (arguments and return pointer).
You will be seriously slowing down the program when using multiple threads if those use "function objects" frequently: Even though many functions can run at the same time, only a single function object can be set up at a time. So at least for that fraction of time it takes for the program to set up the function and actually call it, all other threads trying to run a function will be hanging waiting the the data structure to be unlocked.
You still have to write some non-intuitive code at the beginning and end of each function you want to work without arguments (grabbing the FUNCTIONOBJ_handler structure, unlocking the FUNCTIONOBJ_id_holder structure, accessing arguments through the pointer you grabbed and returning values with non-built-in functions). This increases the chances of bugs drastically if care is not taken, specially some nasty ones:
Increases the chances of deadlocks. If you forget to unlock one of the data structures in any point of your code, you might end up with a program that works fine at some moments, but randomly freeze completely at others (because all function calls without arguments will be hanging waiting for the lock to be freed). That is a risk that happens on multithreaded programs anyways, but by using this you are increasing the amount of code that requires locks unnecessarily (for style purposes).
Complicates the use of recursive functions: Every time you call the function object you'll have to go through the set up phrase (even when inside another function object). Also, if you call the recursive function enough times to fill all FUNCTIONOBJ_handler structures the program will deadlock.
Amongst other reasons I might not notice at the moment :p
I'm trying to use g_idle_add() with function that needs multiple arguments. Can I pass them just inline somehow or do I have to create a structure for this?
The main goal is to reduce memory consumption, everything else is secondary.
static gboolean checker(gpointer plugin, int toggle){
...
return FALSE;
}
g_idle_add(checker, ??? plugin, 0 ??? );
The function you pass to g_idle_add needs to have a signature matching the GSourceFunc type, which means it has to take exactly one pointer argument. You'll have to allocate a structure on the heap (NOT the stack as a commenter has suggested, that will only be valid for as long as the function creating it runs) containing the information you need. Something like this:
struct checker_arguments {
gpointer plugin;
int toggle;
};
static gboolean checker(gpointer data) {
struct checker_arguments *args = data;
/* Do stuff with args->plugin and args->toggle */
g_slice_free1(args, sizeof(*args));
return FALSE;
}
struct checker_arguments *args = g_slice_alloc(sizeof(*args));
args->plugin = plugin;
args->toggle = 0;
g_idle_add(checker, args);
Because you're concerned with memory consumption, I used slice allocation in this example rather than the normal heap allocation. Slice allocation is more efficient for objects of fixed size.
I'm trying to share a variable with c and tcl, the problem is when i try to read the variable in the c thread from tcl, it causes segmentation error, i'm not sure this is the right way to do it, but it seems to work for ints. The part that is causing the segmentation fault is this line is when i try to print "Var" but i want to read the variable to do the corresponding action when the variable changes.
Here is the C code that i'm using
void mode_service(ClientData clientData) {
while(1) {
char* Var = (char *) clientData;
printf("%s\n", Var);
usleep(100000); //100ms
}
}
static int mode_thread(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
Tcl_ThreadId id;
ClientData limitData;
limitData = cdata;
id = 0;
Tcl_CreateThread(&id, mode_service, limitData, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS);
printf("Tcl_CreateThread id = %d\n", (int) id);
// Wait thread process, before returning to TCL prog
int i, aa;
for (i=0 ; i<100000; i++) {aa = i;}
// Return thread ID to tcl prog to allow mutex use
Tcl_SetObjResult(interp, Tcl_NewIntObj((int)id));
printf("returning\n");
return TCL_OK;
}
int DLLEXPORT Modemanager_Init(Tcl_Interp *interp){
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
if (Tcl_PkgProvide(interp, "PCIe", "1.0") == TCL_ERROR) {
return TCL_ERROR;
}
// Create global Var
int *sharedPtr=NULL;
//sharedPtr = sharedPtr = (char *) Tcl_Alloc(sizeof(char));
Tcl_LinkVar(interp, "mode", (char *) &sharedPtr, TCL_LINK_STRING);
Tcl_CreateObjCommand(interp, "mode_thread", mode_thread, sharedPtr, NULL);
return TCL_OK;
}
In the tcl code, i'm changing the variable mode whenever the user presses a button for example:
set mode "Idle"
button .startSamp -text "Sample Start" -width 9 -height 3 -background $btnColor -relief flat -state normal -command {set mode "Sampling"}
set threadId [mode_thread]
puts "Created thread $threadId, waiting"
Your code is a complete mess! You need to decide what you are doing and then do just that. In particular, you are using Tcl_LinkVar so you need to decide what sort of variable you are linking to. If you get a mismatch between the storage, the C access pattern and the declared semantic type, you'll get crashes.
Because your code is in too complicated a mess for me to figure out exactly what you want to do, I'll illustrate with less closely related examples. You'll need to figure out from them how to change things in your code to get the result you need.
Linking Integer Variables
Let's do the simple case: a global int variable (declared outside any function).
int sharedVal;
You want your C code to read that variable and get the value. Easy! Just read it as it is in scope. You also want Tcl code to be able to write to that variable. Easy! In the package initialization function, put this:
Tcl_LinkVar(interp /* == the Tcl interpreter context */,
"sharedVal" /* == the Tcl name */,
(char *) &sharedVal /* == pointer to C variable */,
TCL_LINK_INT /* == what is it! An integer */);
Note that after that (until you Tcl_UnlinkVar) whenever Tcl code reads from the Tcl variable, the current value will be fetched from the C variable and converted.
If you want that variable to be on the heap, you then do:
int *sharedValPtr = malloc(sizeof(int));
C code accesses using *sharedValPtr, and you bind to Tcl with:
Tcl_LinkVar(interp /* == the Tcl interpreter context */,
"sharedVal" /* == the Tcl name */,
(char *) sharedValPtr /* == pointer to C variable */,
TCL_LINK_INT /* == what is it! An integer */);
Linking String Variables
There's a bunch of other semantic types as well as TCL_LINK_INT (see the documentation for a list) but they all follow that pattern except for TCL_LINK_STRING. With that, you do:
char *sharedStr = NULL;
Tcl_LinkVar(interp, "sharedStr", (char *) &sharedStr, TCL_LINK_STRING);
You also need to be aware that the string will always be allocated with Tcl_Alloc (which is substantially faster than most system memory allocators for typical Tcl memory usage patterns) and not with any other memory allocator, and so will also always be deallocated with Tcl_Free. Practically, that means if you set the string from the C side, you must use Tcl_Alloc to allocate the memory.
Posting Update Notifications
The final piece to note is when you set the variable from the C side but want Tcl to notice that the change has set (e.g., because a trace has been set or because you've surfaced the value in a Tk GUI), you should do Tcl_UpdateLinkedVar to let Tcl know that a change has happened that it should pay attention to. If you never use traces (or Tk GUIs, or the vwait command) to watch the variable for updates, you can ignore this API call.
Donal's answer is correct, but I try to show you what you did with your ClientData.
To clarify: All (or almost all, Idk) Tcl functions that take a function pointer also take a parameter of type ClientData that is passed to your function when Tcl calls it.
Let's take a look at this line:
Tcl_CreateObjCommand(interp, "mode_thread", mode_thread, NULL, NULL);
// ------------------------------------------------------^^^^
You always pass NULL as ClientData to the mode_thread function.
In the mode_thread function you use the passed ClientData (NULL) to pass it as ClientData to the new Thread:
limitData = cdata;
// ...
Tcl_CreateThread(&id, mode_service, limitData, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS);
In the mode_service function you use the ClientData (which is still NULL) as pointer to a char array:
char* Var = (char *) clientData;
Which is a pointer to the address 0x00.
And then you tell printf to dereference this NULL pointer:
printf("%s\n", Var);
Which obviously crashes your program.