0

In Cython, how can I convert produce a C string (char *) representation of a C double without using Python objects (e.g. bytes or str) as an intermediate?

In fact, I have defined my function in a C-extension file (.pyx) as follows:

cdef void function(self, char* var1) nogil:

    cdef char* chaine =""
    cdef double inter = 0.0
    #Here there is some treatment which modifies the value of the local variable 'inter' so that it contains a double value different from 0
    strcat(chaine ,  "(")
    strcat(chaine , <char*>inter)
    strcat(chaine ,  ")**beta")

    strcpy(&var1,  chaine)

After compilation of the file, I have the errors C2440 : impossible de convertir de 'double' en 'char*' and C2168 : strcat nombre de paramètres de fonction intrinséque insuffisant

How can I fix the problem please?

ks1322
  • 33,961
  • 14
  • 109
  • 164
koukou
  • 77
  • 5
  • Please read [ask] and the [help], try to provide a [mcve] and explain why your code doesn't work. If you have no code, there is little to no chance that you will get help from this site. – Iharob Al Asimi Apr 17 '18 at 16:28
  • Your code has undefined behavior. You need to avoid doing this in [tag:c] or learn exactly what are c strings and how they work. – Iharob Al Asimi Apr 17 '18 at 16:56
  • I tried to simplify the defenition of the function because it is more complicated in the real code, there is a lot of treatment inside. – koukou Apr 17 '18 at 16:59
  • It doesn't matter. There is a fundamental error with the code that stems from a lack of knowledge about c strings and memory management. – Iharob Al Asimi Apr 17 '18 at 17:00
  • Sorry, I am really a beginner in coding cython code :/ – koukou Apr 17 '18 at 17:03
  • @koukou I suspect that you'd be _much_ better doing this in Python. This doesn't look like code that should be rate-limiting, so Python strings are probably preferable to using C. (And if you just want to make a `nogil` function, then why? You probably don't need to...) – DavidW Apr 17 '18 at 17:11
  • In fact, the example of this function is taken from the source code of a package from Anaconda/scikit-learn. I am just fitting this code to my contribution. So, the added code should respect the structure already presented. – koukou Apr 17 '18 at 19:17
  • You can use a small `with gil:` block and put some Python code there. There might be a small speed cost, but you'll probably find it a lot easier. – DavidW Apr 17 '18 at 19:59
  • In addition to the good comments above, you could have a look at `stdio.snprintf`, for a concrete example see https://stackoverflow.com/a/9835220/4121573 – Adonis Apr 18 '18 at 10:06

1 Answers1

2

Setting aside the issue of whether or not it even is worth doing this at the python or C level, it looks like there are several critical misunderstandings at the C level presented in your sample code. There is a lot of cover, so I will just give few pointers to help steer you in the right direction; feel free to post a corrected version of your code as an answer once you feel more comfortable with C and cython.

First, a word about pointers. A pointer is just a variable that holds a memory address. This memory address "points" to some contents in memory. Here is a simple sample that might clear this up:

cdef int a_number = 42#just a regular int, nothing special here :)
cdef int* a_pointer = &a_number#"referencing" to get the address of a_number
cdef int b_number = a_pointer[0]#"dereferencing" to get the value at a_pointer
#note the dereferencing syntax is different in cython than in C!!!

Second is how functions work. In C, everything is pass-by-value. This means that whenever you pass parameters to a function, a copy of the parameter is made and operations take place on this copy. This includes pointers; if you try to set your var1 pointer like you are attempting in function, the actual var1 pointer is unchanged and only a local copy within the scope of function is being modified. Clearly not what we want!

Third, we need to see how strings are represented in C. Strings are basically a list of characters that you care about, followed by a null terminator \0. I am sure there are lots of sources you can read online about the difference between say char* and char[], and I strongly suggest you take a look at them. I will just say here that char* is just a pointer, and so it only points to the first character. char* also has no concept of the length of the string.

Once you have a good handle of all of these concepts, you can then start looking at functions on the linux man pages like strcpy and strcat. I would also look up sprintf, which is sort of similar to python's format and might be smarter than concatenating a bunch of pieces together. Hope this helps you on your learning journey, and good luck!

CodeSurgeon
  • 2,435
  • 2
  • 15
  • 36