GNU Guile SCM to char* - memory

I am relative new to FFI and GNU Guile, and I am writing bindings to a library that heavily uses char* variables. Here is code from function, that wraps C function:
static inline char*
scm_to_ascii_string(SCM string)
{
return SCM_UNBNDP(SCM) ? NULL
: scm_to_stringn(string, NULL, "ascii", SCM_FAILED_CONVERSION_ERROR);
}
SCM_DEFINE(func, "func", ...)
{
...
char *server_pass = scm_to_ascii_string(scm_server_pass);
char *username = scm_to_ascii_string(scm_username);
char *realname = scm_to_ascii_string(scm_realname);
}
Problem is that any call to conversion function can throw error, leaving me with memory leak.
What can I do about it?

You could make the output part an argument eg:
void scm_to_ascii_string(SCM string, char* &out);
edit:
I guess you meant what exception handler methods are there on the c side, I think there might be something on that in the manual in one of the two sections on programming stuff in C.

Related

Using SNMP++ method with callback in .mm file

I am using SNMP++ library in my project and everything works fine. However, there is a method where I need to get callback in my .mm file. Now when I am creating a block and passing it to that function as parameter, it throws an error "No matching member function for call to 'get_bulk'". Here is the piece of code:
void(^callbackFunc)(int,Snmp*,Pdu&,SnmpTarget&,void*);
callbackFunc = ^(int i,Snmp* s,Pdu& p,SnmpTarget& t,void* v) {
};
snmp.get_bulk(pdu, *target, l_repeaters, l_repetitions,callbackFunc);
Also, here is the function signature for "get_bulk" function:
int Snmp::get_bulk(Pdu &pdu, // pdu to use
const SnmpTarget &target, // destination target
const int non_repeaters, // number of non repeaters
const int max_reps, // maximum number of repetitions
const snmp_callback callback,// callback to use
const void * callback_data) // callback data
{
pdu.set_type( sNMP_PDU_GETBULK_ASYNC);
return snmp_engine( pdu, non_repeaters, max_reps, target,
callback, callback_data);
}
What should I pass in 'callback' type?This is the typedef for SNMP_callback:
typedef void (*snmp_callback)(int reason, Snmp *session,
Pdu &pdu, SnmpTarget &target, void *data);
I am stuck on this for the past 4-5 hours now and I can't figure out how to resolve this.
Apple's blocks are not convertible to function pointers, as they also contain data (captured variables, etc.) and a reference counting mechanism. You will need to pass a free function, static C++ class member function, or a C++ non-capturing lambda as the callback.
The lambda is the closest syntactically to a block; only non-capturing lambdas are convertible to a function pointer, however, so you will need to do the capturing "by hand" by passing a pointer to a context struct or similar through the void* callback_data argument which presumably is passed through to the callback as void* data.
The lambda will look something like this:
snmp_callback callback =
[](int reason, Snmp *session, Pdu &pdu, SnmpTarget &target, void *data)
{
// context_struct_type* context = static_cast<context_struct_type*>(data);
};

Is there a method to allow pure c file to use <Metal/Metah.h>?

In other words, could ios's metal be used in pure c file? Thanks for reviewing.
The Metal API is Objective-C, however that shouldn't present a problem as you can provide C functions within Objective-C implementation files so the rest of your C-based code can call these functions.
For example (I don't know the Metal API, so this is gibberish):
metalapi.h:
// This is a C function...
extern int doThingWithMetal(int someParam, const char *otherParam);
metalapi.m:
#import <Metal/Metal.h>
// ... implemented in Objective-C
int doThingWithMetal(int someParam, const char *otherParam)
{
return [someMetalClass someMethod:someParam] == SOME_VALUE ? 0 : 1;
}
otherfile.c
#include "metalapi.h"
....
if (doThingWithMetal(1, "Hello") == 0) {
...
}

What is the type of pthread_mutex_t?

From: https://www.sourceware.org/pthreads-win32/manual/pthread_mutex_init.html
Variables of type pthread_mutex_t can also be initialized statically,
So, what is the type of pthread_mutex_t?
That is the type. The implementation underneath is often a struct and you can look in the header files if you really care about the specific implementation of the library you're using, but those details don't matter for using it, you just care about the pthread_mutex_t type.
pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
From pthreadtypes.h, in my Linux distribution its definition is pretty clear as a typedef for a union, as defined below:
/* Data structures for mutex handling. The structure of the attribute
type is not exposed on purpose. */
typedef union
{
struct __pthread_mutex_s
{
int __lock;
unsigned int __count;
int __owner;
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
unsigned int __nusers;
__extension__ union
{
int __spins;
__pthread_slist_t __list;
};
} __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;
} pthread_mutex_t;
You'll want to use it as their defined type, pthread_mutex_t of course -- since this type will vary by OS / distribution / etc.
pthread_mutex_t is a type, so it doesn't have a type itself. If you are curious about what this type is an alias for, on my machine I have:
struct _opaque_pthread_mutex_t {
long __sig;
char __opaque[__PTHREAD_MUTEX_SIZE__];
};
and then
typedef struct _opaque_pthread_mutex_t __darwin_pthread_mutex_t;
and finally:
typedef __darwin_pthread_mutex_t pthread_mutex_t;

Is "Oops: ; return error;" a valid method declaration in C?

#include <stdio.h>
#include <AssertMacros.h>
int main( int argc, char* argv[] )
{
int error = 1;
verify_noerr( error );
require_noerr( error, Oops ); //<---- Is Oops a callback method?
printf("You shouldn't be here!\n");
Oops: ; // <--v____ Is this a method declaration?
return error; // <--^ Why the ':' followed by the ';'?
}
This code is from iOS documentation from 2006. I realize that in C the default return type for a method with no declared return type is int. But is this really a method that is leaning on that principle? And why the colon semicolon? My last thought was that its a C block, but Wikipedia says otherwise.
I'm stumped.
This:
Oops: ;
is a label, which can be the target of a goto.
I'm guessing that require_noerr is a macro that expands to a goto to the given label if error is an error code.
You'd use this system to exit from a function when an error occurred. It allows for cleanup code between the label and the end of the function (which a simple if (error) return; doesn't).
this is called a label in C programming.
in c code you can use goto to jump to this label
goto Oops;

what is wrong with following pthread program?

I am not able to execute pthreads program in c. Please tell me what is wrong with the following program. I am neither getting any error nor expected output.
void *worker(void * arg)
{
int i;
int *id=(int *)arg;
printf("Thread %d starts\n", *id );
}
void main(int argc, char **argv)
{
int thrd_no,i,*thrd_id,rank=0;
void *exit_status;
pthread_t *threads;
thrd_no=atoi(argv[1]-1);
thrd_id= malloc(sizeof(int)*(thrd_no));
threads=malloc(sizeof(pthread_t)*(thrd_no));
for(i=0;i<thrd_no;i++)
{
rank=i+1;
thrd_id[i]=pthread_create(&threads[i], NULL, worker, &rank);
}
for(i=0;i<thrd_no;i++)
{
pthread_join(threads[i], &exit_status);
}
}
thrd_no = atoi(argv[1] - 1); likely doesn't do what you intended; the way argv is normally passed into a new process and parsed into a C array, argv[1] - 1 is probably pointing at \0 (specifically, the \0 at the end of argv[0]). (More generally, indexing backwards off the start of a string is rarely correct.) The result is that atoi() will return 0 and no threads will be created. What did you actually intend to do there?
You are passing the same address &rank to each thread, so id and *id is the same for all your worker-s.
You should better allocate on the heap the address you pass to each worker routine.
You might also include <stdint.h and use intptr_t, e.g.
void worker (void* p)
{
intptr_t rk = (intptr_t) p;
/// etc
}
and call
intptr_t rank = i + 1;
thrd_id[i]=pthread_create(&threads[i], NULL, worker, (void*)rank);
You should learn to use a debugger and compile with all warnings and debug information, i.e. gcc -Wall -g (and improve your code till it gets no warnings, then use gdb)
code segment rank=i+1;
thrd_id[i]=pthread_create(&threads[i], NULL, worker, &rank);
will produce race condition.

Resources