Recently I get interested in CUDA and it seems much natural to convert C programs into CUDA than Fortran to CUDA (Apart from the main question in this post, is this really true?).
So I am learning C now, and bit surprised that the if statements in C behaves in a quite different way than the Fortran.
For example, the following code works just as expected in Fortran
program test
real(kind=selected_real_kind(15)), allocatable :: arr_double(:)
integer , allocatable :: arr_int(:)
logical :: flag_int, flag_double
flag_int = .false.
flag_double = .true.
if (flag_int) then
allocate(arr_int(10))
arr_int = 1
print *, arr_int
else if (flag_double) then
allocate(arr_double(10))
arr_double = 1.
print *, arr_double
end if
if (flag_int) then
deallocate(arr_int)
else if (flag_double) then
deallocate(arr_double)
end if
end program
and its output is like following - again, it is as expected.
1.00000000000000 1.00000000000000 1.00000000000000
1.00000000000000 1.00000000000000 1.00000000000000
1.00000000000000 1.00000000000000 1.00000000000000
1.00000000000000
However, its C counterpart does not work and gives error even in the compile-time (icc)
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main() {
size_t dim1;
bool flag_int, flag_double;
flag_int = false;
flag_double = true;
if (flag_int) {
int (*arr1d) = calloc(dim1, sizeof(*arr1d));
}else if(flag_double) {
double (*arr1d) = calloc(dim1, sizeof(*arr1d));
}
free(arr1d);
}
It seems that the compile fails because in C the code lines under if () {...} is only local inside the {...}.
Then, if I want to allocate different type of array (i.e. int or double) depending on some if statement, then what would be the best practice to do this?
ps. I want to note that I encountered this problem just playing with the C, and not going to use this kind of ugly code in my actual work.
I don't know much Fortran, but I see that in your Fortran code you have mentioned both arr_double and arr_int up at the top, right under program test. I assume this makes those identifiers available for the later allocate and deallocate statements.
You can do the same sort of declaration in C.
#include <stdlib.h>
#include <stdbool.h>
int main() {
size_t dim1 = 10;
double *arr_double = NULL;
int *arr_int = NULL;
bool flag_int, flag_double;
flag_int = false;
flag_double = true;
if (flag_int) {
arr_int = calloc(dim1, sizeof *arr_int);
} else if (flag_double) {
arr_double = calloc(dim1, sizeof *arr_double);
}
free(arr_int);
free(arr_double);
}
Note that I don't have to check the flags before deallocating with free, because I initialized both arr_int and arr_double to null pointers, and free is required to do nothing when given a null pointer.
As for “what would be the best practice to do this?”, your example is so much a toy program that I don't think there's much useful advice to give.
Related
because of my limited knowledge in C and SWIG i couldn't manage to adopt any public example for converting c-pointer chars to tcl strings ....
I always get stuck at the problem that my tcl variable just doesn't get dereferenced
like this :
tcl_str = _30e84c05ef550000_p_stringout2
string_pointer.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "string_pointer.h"
stringout2 Itla_Get_Model_Version (int laser, char * mv_string)
{
stringout2 * pointer2;
char *mod_ver ="PPCL600";
pointer2 = malloc( sizeof(stringout2) );
pointer2-> modelvers= *mod_ver;
printf ( "Itla_Get_Model_Version : read %s \n", mod_ver );
return *pointer2 ;
}
string_pointer.h
#include <sys/types.h>
#include <sys/resource.h>
typedef struct {
char * modelvers;
} stringout2;
stringout2 Itla_Get_Model_Version (int laser, char * mv_string) ;
string_pointer.swig
/* File : string_pointer.swig */
%module string_pointer
%{
#include "string_pointer.h"
%}
%include "typemaps.i"
%include "cpointer.i"
%include "cstring.i"
%typemap(argout) char* (char tmp) %{
$1 = &tmp;
%}
stringout2 Itla_Get_Model_Version (int laser, char *OUTPUT) ;
%include "string_pointer.h"
test.tcl
load ./string_pointer.so
proc test { laser } {
scan [Itla_Get_Model_Version $laser ] %s a
puts "$a "
return $a
}
set name [test 1 ]
puts "Itla_Get_Model_Version= $name"
when executing the tcl-script you get :
Itla_Get_Model_Version : read PPCL600
_f0a759f8d9550000_p_stringout2
Itla_Get_Model_Version= _f0a759f8d9550000_p_stringout2
so i finally need to dereference the Pointer to its value ...
But i don't know how to succeed.....
The C-function is given and can't be modified !
Anybody out there, knowing how to do it ?
If your strings are basically ASCII or UTF-8, all you need to do is to tell SWIG that your function has allocated the string it is returning. For details see, the SWIG docs on C strings.
yourcode.c
char *Itla_Get_Model_Version (int laser, char * mv_string) {
// I assume this is a proxy for something more complicated...
const char *mod_ver ="PPCL600";
size_t len = strlen(mod_ver) + 1;
char *output = malloc(len);
memcpy(output, mod_ver, len);
printf ( "Itla_Get_Model_Version : read %s \n", mod_ver );
return output;
}
yourcode.h
char *Itla_Get_Model_Version(int laser, char * mv_string);
yourcode.swig
/* Tell SWIG that this function returns something to be freed */
%newobject Itla_Get_Model_Version
/* And now we can use the standard C header */
%include "yourcode.h"
If the above simple solution doesn't work…
Things get a lot more complicated if you are using a different encoding for your strings or if you wrap them inside a structure (as you did in your question). That's when you need a typemap, particularly ones of the Tcl variety. Correctly writing a typemap depends on understanding the semantics of the values that you are producing and/or consuming and the semantics of the language that you're using. Assuming you want the wrapping, here's a very simple output typemap that might work:
%typemap(out) stringout2* {
Tcl_SetObjResult(interp, Tcl_NewStringObj($1->modelvers, -1));
free($1);
}
Your function also needs to be modified to return a stringout2* by doing return pointer2;, and not a stringout2 since otherwise you will be leaking memory on every call. You can return a stringout2, but if you are doing that then you should not allocate it with malloc, but rather keep it as a structure directly in a local variable.
In that case, the typemap you'd use is:
%typemap(out) stringout2 {
Tcl_SetObjResult(interp, Tcl_NewStringObj($1.modelvers, -1));
}
(Note the different type, different access to the field, and lack of free.)
And your structure should be declared as containing a const char * if it really is that.
If you have strings in a different encoding (and it isn't ISO 8859-1, for which you can cheat and use a binary string using Tcl_NewByteArrayObj; that's also what you want for slabbing a chunk of binary data over) then you'll need to write a typemap using Tcl_ExternalToUtfDString, and the amount of boilerplate code goes up. Tcl insists that its internal strings are in (almost) UTF-8, and ASCII is OK too as that's a strict subset; everything else must be converted.
Ask another question if that's what you need. You probably are either dealing with ASCII or binary data, so I'll leave (quite a bit more complex!) encoding conversion alone until requested.
Problem statement
The main part of my code is in C (called from Python). The C-part calls functions written in Fortran. Possible errors are propagated using an error-code and an error-string with a description of the error.
The problem is that I cannot seem to get the correct interface to write the string in Fortran and read/copy/manipulate it in C. The code below outlines what I want to do, the comments with marked with * ... * indicate where extensions are needed.
C
// global variable: read from Python if an error is encountered
char* error_string;
// template for the Fortan-subroutine
void fortran_calculation_( double* , int* );
int heavy_calculation( double* x )
{
int error_code;
// ... some code ...
// * should accept and write "error_string" *
fortran_calculation_( x , &error_code );
if ( error_code )
{
error_string = "TO BE WRITTEN BY FORTRAN > REMOVE!!";
return 1;
}
// ... some code ...
return 0;
}
Fortran
subroutine fortran_calculation_(x,error_code)
implicit none
! * include "error_string" as argument *
real*8 :: x
integer :: error_code
! ... some code ...
if ( ... ) then
! * write "error_string" *
error_code = 1
return
end if
return
end subroutine
I've tried many things, but I cannot seem to get it working...
You have two problems. One, how to access a C global variable from Fortran. This one is relatively straightforward, create an interface in a module with iso_c_binding. See https://gcc.gnu.org/onlinedocs/gfortran/Interoperable-Global-Variables.html for an example.
However, the trickier problem is that you have defined your error_string as a pointer to char. That means that your Fortran code must allocate the string before writing to it. The Fortran allocatable and pointer variables work with descriptors, not raw pointers, so you must first create an interface to the C malloc function. Only after that you can write to it. Something like:
module my_error_string
use iso_c_binding
interface
type(c_ptr) function c_malloc(size) bind(C, name="malloc")
use iso_c_binding
integer(kind=c_size_t), value :: size
end function c_malloc
end interface
type(c_ptr), bind(C) :: error_string
contains
subroutine write_error(str)
character(len=*) :: str
character, pointer :: fstr(:)
integer(c_size_t) :: strlen
integer :: i
strlen = len(str, kind=c_size_t) + 1_c_size_t
error_string = c_malloc(strlen)
if (.not. c_associated(error_string)) then
call perror("error_string is a null pointer => malloc failed?!")
stop 1
end if
call c_f_pointer(error_string, fstr, shape=[strlen])
do i = 1, len(str)
fstr(i) = str(i:i)
end do
fstr(strlen) = c_null_char
end subroutine write_error
end module my_error_string
(It might be simple to change the interface such that you instead pass an allocated C string to the Fortran function to fill in, or perhaps use a callback function. But the above works, if that's what you want.)
Here is a shamefully ugly "solution" to your problem, based on the design you provided.
main.c:
#include <stdio.h>
#include <string.h>
char error_string_[512];
void fortan_calculation_( double*, int*, int* );
int main() {
double d = 2.5;
int l, i = 3;
memset( error_string_, 0, 512 );
fortan_calculation_( &d, &i, &l );
error_string_[l] = 0;
printf( "After call: '%s'\n", error_string_ );
}
error.f90:
subroutine fortan_calculation( d, i, l )
implicit none
character(512) str
common /error_string/ str
double precision d
integer i, l
str = "Hello world!"
l = len_trim( str )
end subroutine fortan_calculation
Compilation and test:
$ gcc -c main.c
$ gfortran -c error.f90
$ gcc main.o error.o -lgfortran
$ ./a.out
After call: 'Hello world!'
But that is just disgusting code: it assumes a lot of (arguably) common practices for Fortran compilers, whereas it exists some ways of linking properly C and Fortran using the iso_c_binding Fortran module.
I'll have a look and see if I can come up with a proper solution to that.
EDIT: actually, there's a nice SO page about that available.
Trying out Google protocol buffers for my code in C language.
messagefile.proto
===================
mesage othermessage
{
optional string otherstring = 1;
}
message onemessage
{
optional string messagestring = 1;
optional int32 aninteger = 2;
optional othermessage otr_message= 3;
}
==============================================
--> protoc-c messagefile.proto --c_out=./
this resulted in two files
--> messagefile.pb-c.c and messagefile.pb-c.h
Now my code file which would try to use the
simpleexample.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "messagefile.pb-c.h"
#include <stdbool.h>
int main(int argc, const char * argv[])
{
onemessage msg = ONE__MESSAGE__INIT; //from generated .h code file
void *buf;
unsigned int len;
char *ptr;
//integer initialization
msg.has_aninteger = true;
msg.aninteger = 1;
//accessing the string in onemessage
msg.messagestring = malloc(sizeof("a simple string"));
strncpy(msg.messagestring,"a simple string",strlen("a simple string"));
//trying to initialize the string in the nested structure othermessage
msg.otr_message = malloc(sizeof(othermessage));
msg.otr_message->otherstring = malloc(sizeof("a not so simple string"));
strncpy(msg.otr_message->otherstring,"a not so simple string",strlen("a not so simple string"));
//lets find the length of the packed structure
len = one_message__get_packed_size(&msg); //from generated .h code
//lets arrange for as much size as len
buf = malloc(len);
//lets get the serialized structure in buf
one_message__pack_to_buffer(&msg,buf); //from generated code
//write it to a stream, for now the screen
fwrite(buf,len,1,stdout);
//free buffer
free(buf);
return 0;
}
I compile it as gcc -o testout messagefile.pb-c.c simpleexample.c -lprotobuf-c
The Problem I am facing is when trying to initialize the nested othermessage variables and then call the get_packed_size it throws a segmentation fault.
I tried various combinations and I can say that whenever having strings in a nested class, I am facing problem to access those using google protoc.
Am i missing something? Is there anything wrong.
Can anyone please help.
note:There might be a few general syntax errors please ignore them.
ThankYou.
note:There might be a few general syntax errors please ignore them.
Err... they are kinda hard to ignore since your code does not compile :-)
Anyway, apart from the syntax errors, you need to make several corrections to your code. In order to use the field otr_message, it is not sufficient to just malloc() it. You also need to initialize it so the headers in the message get the right values. This is done with init(), like this:
//trying to initialize the string in the nested structure othermessage
msg.otr_message = malloc(sizeof(othermessage));
othermessage__init(msg.otr_message);
Then you use the wrong function to do the packing to your own array. As explained here, you need to use pack() as opposed to pack_to_buffer(), like this:
//lets get the serialized structure in buf
onemessage__pack(&msg,buf); //from generated code
Finally, your strncpy() invocations have a mistake. The length calculated with strlen() does not include the null terminator, which you do need. So you need to take strlen()+1 or use sizeof(), like this:
strncpy(msg.messagestring,"a simple string",sizeof("a simple string"));
After making those changes, the example worked for me:
$ ./testout
a simple string
a not so simple string
I would like to be able to use my own memory allocation function for certain data structures (real valued vectors and arrays) in R. The reason for this is that I need my data to be 64bit aligned and I would like to use the numa library for having control over which memory node is used (I'm working on compute nodes with four 12-core AMD Opteron 6174 CPUs).
Now I have two functions for allocating and freeing memory: numa_alloc_onnode and numa_free (courtesy of this thread). I'm using R version 3.1.1, so I have access to the function allocVector3 (src/main/memory.c), which seems to me as the intended way of adding a custom memory allocator. I also found the struct R_allocator in src/include/R_ext
However it is not clear to me how to put these pieces together. Let's say, in R, I want the result res of an evaluation such as
res <- Y - mean(Y)
to be saved in a memory area allocated with my own function, how would I do this? Can I integrate allocVector3 directly at the R level? I assume I have to go through the R-C interface. As far as I know, I cannot just return a pointer to the allocated area, but have to pass the result as an argument. So in R I call something like
n <- length(Y)
res <- numeric(length=1)
.Call("R_allocate_using_myalloc", n, res)
res <- Y - mean(Y)
and in C
#include <R.h>
#include <Rinternals.h>
#include <numa.h>
SEXP R_allocate_using_myalloc(SEXP R_n, SEXP R_res){
PROTECT(R_n = coerceVector(R_n, INTSXP));
PROTECT(R_res = coerceVector(R_res, REALSXP));
int *restrict n = INTEGER(R_n);
R_allocator_t myAllocator;
myAllocator.mem_alloc = numa_alloc_onnode;
myAllocator.mem_free = numa_free;
myAllocator.res = NULL;
myAllocator.data = ???;
R_res = allocVector3(REALSXP, n, myAllocator);
UNPROTECT(2);
}
Unfortunately I cannot get beyond a variable has incomplete type 'R_allocator_t' compilation error (I had to remove the .data line since I have no clue as to what I should put there). Does any of the above code make sense? Is there an easier way of achieving what I want to? It seems a bit odd to have to allocate a small vector in R and the change its location in C just to be able to both control the memory allocation and have the vector available in R...
I'm trying to avoid using Rcpp, as I'm modifying a fairly large package and do not want to convert all C calls and thought that mixing different C interfaces could perform sub-optimally.
Any help is greatly appreciated.
I made some progress in solving my problem and I would like to share in case anyone else encounters a similar situation. Thanks to Kevin for his comment. I was missing the include statement he mentions. Unfortunately this was only one among many problems.
dyn.load("myAlloc.so")
size <- 3e9
myBigmat <- .Call("myAllocC", size)
print(object.size(myBigmat), units = "auto")
rm(myBigmat)
#include <R.h>
#include <Rinternals.h>
#include <R_ext/Rallocators.h>
#include <numa.h>
typedef struct allocator_data {
size_t size;
} allocator_data;
void* my_alloc(R_allocator_t *allocator, size_t size) {
((allocator_data*)allocator->data)->size = size;
return (void*) numa_alloc_local(size);
}
void my_free(R_allocator_t *allocator, void * addr) {
size_t size = ((allocator_data*)allocator->data)->size;
numa_free(addr, size);
}
SEXP myAllocC(SEXP a) {
allocator_data* my_allocator_data = malloc(sizeof(allocator_data));
my_allocator_data->size = 0;
R_allocator_t* my_allocator = malloc(sizeof(R_allocator_t));
my_allocator->mem_alloc = &my_alloc;
my_allocator->mem_free = &my_free;
my_allocator->res = NULL;
my_allocator->data = my_allocator_data;
R_xlen_t n = asReal(a);
SEXP result = PROTECT(allocVector3(REALSXP, n, my_allocator));
UNPROTECT(1);
return result;
}
For compiling the c code, I use R CMD SHLIB -std=c99 -L/usr/lib64 -lnuma myAlloc.c. As far as I can tell, this works fine. If anyone has improvements/corrections to offer, I'd be happy to include them.
One requirement from the original question that remains unresolved is the alignment issue. The block of memory returned by numa_alloc_local is correctly aligned, but other fields of the new VECTOR_SEXPREC (eg. the sxpinfo_struct header) push back the start of the data array. Is it somehow possible to align this starting point (the address returned by REAL())?
R has, in memory.c:
main/memory.c
84:#include <R_ext/Rallocators.h> /* for R_allocator_t structure */
so I think you need to include that header as well to get the custom allocator (RInternals.h merely declares it, without defining the struct or including that header)
This is a bit frustrating. I've been working on this for a while now, and I can't seem to get this method to work like it says it does.
#include "icalrecur.h"
#include <time.h> /* for time() */
#include <stdio.h>
int get_occurrences(char* rrule, time_t start, int count)
{
//char* rule; /* rule string */
// *rule = PG_GETARG_CHAR(0);
time_t *result[count]; /* output array */
icalrecur_expand_recurrence(rrule, start, count, *result);
return (time_t) *result;
}
//time_t *output[5*8];
void main() {
time_t right_now = time(0);
char *_rrule = "FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH";
get_occurrences(_rrule, right_now, 5);
}
I save this test file as ical_recur.h. Then I type in bash:
gcc -I/usr/local/libical/include/libical -L/usr/local/libical/lib/ -lical -o hello ical_recur.c
To include the libical.a libraries. The include/libical directory has icalrecur.h in it, so I really don't even need to be including the whole ical library.
~: ./hello
Segmentation fault
Anytime I change around any pointers, it starts complaining about something during compilation. Can anyone get this to work?? Source files are from Marketcircle on github.
Looking at the documentation it seems that you have an unwanted extra level of indirection - you need to change:
time_t *result[count]; /* output array */
icalrecur_expand_recurrence(rrule, start, count, *result);
to:
time_t result[count]; /* output array */
icalrecur_expand_recurrence(rrule, start, count, result);
Also you're passing a read-only string literal to a function which expects a char * - this should at least give you a compiler warning (hint: always use gcc -Wall ..., read the warnings carefully, understand them and fix them). main() should look more like this:
int main() {
time_t right_now = time(0);
char _rrule[] = "FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH";
get_occurrences(_rrule, right_now, 5);
return 0;
}
Some more problems:
this line doesn't do anything useful, but it's not clear what you're trying to achieve:
char _size = (char)(((int)'0') + sizeof(result));
all those casts are a "code smell" and this should tell you that you're doing something very wrong here
your function is defined as returning an int, but you're trying to cast your array to a time_t and return that, which also makes no sense - again, turn on compiler warnings - let the compiler help you find and fix your mistakes.
Now you can use this extension for postgresql.
Example usage:
SELECT * FROM
unnest(
rrule_get_occurrences('FREQ=WEEKLY;INTERVAL=1;WKST=MO;UNTIL=20200101T045102Z;BYDAY=SA;BYHOUR=10;BYMINUTE=51;BYSECOND=2'::rrule,
'2019-12-07 10:51:02+00'::timestamp with time zone)
);
unnest
------------------------
2019-12-07 10:51:02+00
2019-12-14 10:51:02+00
2019-12-21 10:51:02+00
2019-12-28 10:51:02+00
(4 rows)