473,698 Members | 2,480 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

calling Pyrex results from C

I need to submit C/C++ code for a class. (It's not a programming
class. The choice of language is inertial. I think that it mostly
serves to distract students from the course subject.) I'm fairly
fluent with C but it hurts to think about writing in C when Python
is *so* much more appropriate for these operations.

I'd like to keep my sanity and satisfy the course requirements by
programming in Python and converting the code to C. It looks like
a few people have scratched this itch already, but of the
translators I found, most of them (Python2C, P2C, PyFront) seem to
be dead. Pyrex, however, appears to be well-maintained and is even
available as a Debian package.
http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/

I realize that the goal of Pyrex is to create a module that can be
called from Python. For my need of calling the result from C, the
other utilities are probably more appropriate but I think that
Pyrex could be useful to me for less contrived situations than this
so it's worthwhile to learn more about it.
http://www.cosc.canterbury.ac.nz/~gr...ngWithExternal

You can also use public declarations to make C functions
and variables defined in a Pyrex module available to
external C code. The need for this is expected to be less
frequent, but you might want to do it, for example, if you
are embedding Python in another application as a scripting
language. Just as a Pyrex module can be used as a bridge to
allow Python code to call C code, it can also be used to
allow C code to call Python code.

[...]

You can make C variables and functions defined in a Pyrex
module accessible to external C code (or another Pyrex
module) using the public keyword

I've discovered that as long as everything in the code is cdef-ed,
I can call Pyrex code from my C code. If, however, I so much as
mention anything Pythonish, it segfaults during execution.

For example, this is fine.
cdef public int foo():
cdef int i
i = 123

return(i)

And this results in a segfault.
cdef public int foo():
cdef int i
i = 123
j = 5

return(i)

This means that I can't, for example, make a function that takes a
filename (string), uses PIL to do a bunch of operations, and
returns a string.

Any suggestions (besides "suck it up and do it all in C")?

Thank you.

--kyler
Jul 18 '05 #1
10 2032
[Kyler Laird]
I realize that the goal of Pyrex is to create a module that can be
called from Python.
Or vice-versa. I found Pyrex useful for calling Python modules from
within C programs which were not Python-aware to start with. You may
even write wholly Pyrex programs.
I've discovered that as long as everything in the code is cdef-ed,
I can call Pyrex code from my C code. If, however, I so much as
mention anything Pythonish, it segfaults during execution.


There is some magic needed to establish Python context, not much.
Hoping that it will help, here is a template I use when generating
Pyrex main programs. `%(module)s' shall be replaced by the Pyrex module
name, as Pyrex needs to initialise itself. When Python calls Pyrex,
initialisation occurs automatically at `import' time, but when C
initially calls Pyrex, initialisation should be explicitly launched.

cdef extern void Py_Initialize()
cdef extern void Py_Finalize()
cdef extern void init%(module)s( )

cdef extern int main(int argc, char **argv):
cdef int index, status
Py_Initialize()
init%(module)s( )
import sys
try:
arguments = []
for index from 0 <= index < argc:
arguments.appen d(argv[index])
sys.argv = arguments
result = main_applicatio n()
raise SystemExit, result or 0
except SystemExit, result:
result = str(result)
try:
status = int(result)
except ValueError:
if not result.endswith ('\n'):
result = result + '\n'
sys.stderr.writ e(result)
status = 1
except:
import traceback
traceback.print _exc()
status = 1
Py_Finalize()
return status
--
François Pinard http://www.iro.umontreal.ca/~pinard

Jul 18 '05 #2
Kyler Laird <Ky***@news.Lai rds.org> writes:
[...]
This means that I can't, for example, make a function that takes a
filename (string), uses PIL to do a bunch of operations, and
returns a string.
I don't see why you shouldn't be able to write a module in Pyrex, then
use standard embedding techniques to embed Python and then call your
module with a few C API calls. Or do the same, but also write a Pyrex
cdef function to wrap it all up, so you can just call that as a "plain
old" C function instead of those final few C API calls (you'll still
need other embedding calls, of course, to initialise Python, etc.).

Try the pyrex mailing list if you're stuck.

I'd very definitely check to make sure you aren't going to get marked
down for being a smartass, though (even if you're generating C that
doesn't depend on Python at all, it might still be unreadable).

Any suggestions (besides "suck it up and do it all in C")?


I think I'd do it in C, regardless of whether or not it's allowable to
use Pyrex.
John
Jul 18 '05 #3
On Tue, Jan 20, 2004 at 12:27:33PM -0500, Fran?ois Pinard wrote:
There is some magic needed to establish Python context, not much.
Hoping that it will help, here is a template I use when generating
Pyrex main programs.


Paul started me on this path and you've given me exactly what I need to
keep going.

Thank you!

--kyler
Jul 18 '05 #4
Paul Prescod graciously responded to my plea for help by gently asking
if I had initialized Python. Doh! I had gotten lazy and assumed that
Pyrex would take care of such details. (How could it?!)

Initializing the interpreter seems to have the simple test case I made
working smoothly. Now it's on to bigger and better things...

Pyrex is *so* cool.

Thank you, Paul!

--kyler
Jul 18 '05 #5
[Kyler Laird]
On Tue, Jan 20, 2004 at 12:27:33PM -0500, Fran?ois Pinard wrote:
There is some magic needed to establish Python context, not much.
Hoping that it will help, here is a template I use when generating
Pyrex main programs.

Paul started me on this path and you've given me exactly what I need to
keep going.


Good. :-)

There is also some linking magic, which differs from system to system,
it might be documented in the Python Embedding API, I'm not sure. If
you do not stumble on the proper recipe, I'll share what I use on Linux.
Just ask if you want me to go search into some of my Makefiles :-).

--
François Pinard http://www.iro.umontreal.ca/~pinard

Jul 18 '05 #6
The help I've gotten in this thread has enabled me to complete my
assignment...we ll, at least I can generate C code that spits out
the answer.

I'd like to factor out more of the Python so that my handwritten
C code can do more of the high-level operations. I'm having some
difficulties passing data between my C and the Pyrex code.

One of the first things I thought I'd build is a helper function
to return a string representation of an object. I thought that
this would be fairly straightforward . Unfortunately it segfaults
when called with some Python objects.

Pyrex:
cdef public image_file_open (char* image_filename) :
return(Image.op en(image_filena me))

cdef public image_size(imag e_PIL):
return(Image.si ze)

cdef public char* string(x):
s = str(x)
return(s)

my C:
void *im, *im_size;
im = image_file_open (input_filename );
im_size = image_size(im);
printf("im=%s\n ", string(im));
printf("im_size =%s\n", string(im_size) );

The first call to string() succeeds but the second one fails. I
suspect that I've expected too much of Pyrex again. Do I need to
allocate memory, manipulate reference counts or something like
that?

It's difficult for me to get back to thinking in terms of
passing around data in C ways. I almost forgot what a boon
tuples have been. (Perhaps I need to code in assembly for
awhile to get back in that frame of mind.) Someday I might try
to pass structures between C and Pyrex. I'm slowly getting
comfortable with Pyrex but I can see how my code can get *much*
cleaner once I understand more of its capabilities.

Thank you.

--kyler
Jul 18 '05 #7
Kyler Laird wrote:

Pyrex:
cdef public image_file_open (char* image_filename) :
return(Image.op en(image_filena me))

cdef public image_size(imag e_PIL):
return(Image.si ze)

cdef public char* string(x):
s = str(x)
return(s)

my C:
void *im, *im_size;
im = image_file_open (input_filename );
im_size = image_size(im);
printf("im=%s\n ", string(im));
printf("im_size =%s\n", string(im_size) );

The first call to string() succeeds but the second one fails. I
suspect that I've expected too much of Pyrex again. Do I need to
allocate memory, manipulate reference counts or something like
that?


First, I'd suggest that "integer" is a perfectly good type in both C and
Pyrex so you shouldn't pass around Python objects representing integers.

Second, you aren't checking the return codes of your functions and C has
no exception handling, tracebacks, etc. image_size is probably returning
0 because it is probably throwing an exception because you are asking
for the size attribute of the Image class rather than the image_PIL object.

You actually would have gotten a Pyrex error on your console if your
function were defined to return "int" or "void" because Pyrex would KNOW
that there's no way you are doing exception handling so it would try to
compensate by printing exceptions to the console. But I wouldn't depend
on that feature because it doesn't help for functions that really should
return objects. Better to check your return values.

Once I fix the Image/Image_PIL error your code runs okay on my computer.
But you are walking on thin ice and may just be lucky. It is simply
not possible to work with strings generated at runtime in C without
worrying about memory allocation sometime. In this case I have the
strong suspicion that the string() function is either creating and
destroying a string object and then returning you a pointer to the dead
object's internal memory buffer (bad news!) or simply losing a reference
to the (still living) string object: still not a good thing. Eyeballing
the code I believe the former is the issue. You could check for sure by
adding some printf's to the generated code to look at __pyx_v_s->ob_refcnt.

Why not let Python do the "print" rather than using "printf".

Paul Prescod

Jul 18 '05 #8
On Wed, Jan 21, 2004 at 08:23:53AM -0800, Paul Prescod wrote:
First, I'd suggest that "integer" is a perfectly good type in both C and
Pyrex so you shouldn't pass around Python objects representing integers.
That would be my inclination too if I just had an integer to pass.
Are you suggesting that I should pass tuples of integers as pointers
to (an array of) integers?
Second, you aren't checking the return codes of your functions and C has
no exception handling, tracebacks, etc. image_size is probably returning
0 because it is probably throwing an exception because you are asking
for the size attribute of the Image class rather than the image_PIL object.
I'm trying to keep my examples simple so that it's easy to pick out the
mistakes.
Once I fix the Image/Image_PIL error your code runs okay on my computer.
Grrr...yup, that does it. Dumb mistake - the result of pulling code
out of various places and gluing it together without checks.
But you are walking on thin ice and may just be lucky. It is simply
not possible to work with strings generated at runtime in C without
worrying about memory allocation sometime. In this case I have the
strong suspicion that the string() function is either creating and
destroying a string object and then returning you a pointer to the dead
object's internal memory buffer (bad news!) or simply losing a reference
to the (still living) string object: still not a good thing. Eyeballing
the code I believe the former is the issue. You could check for sure by
adding some printf's to the generated code to look at __pyx_v_s->ob_refcnt.
I feared this was a problem. I'll play with it.
Why not let Python do the "print" rather than using "printf".


Printing is not always my final goal.

Thank you.

--kyler
Jul 18 '05 #9
Paul Prescod <pa**@prescod.n et> writes:
1. How is your teacher going to react when you hand in obfuscated-ish
C code that depends on the whole Python interpreter _and_ PIL?


Shhh...don't tell anyone.
Grades for ECE661 as of Wed Feb 4 15:01:35 2004
Name hw1 hw2
---- ----- -----
Maximums: 100.0 100.0
Laird, Kyler 100.0 100.0
Class Average: 93.8 86.6
Class Standard Deviation: 20.1 24.3

This is Computer Vision, not Introduction to Pointers and Memory Allocation.
Pyrex frees me to concentrate on the course material.

(And I *need* to concentrate on the course material. I'm in a class full of
incredibly smart people with a lot more background in the subject. Pyrex
helps me keep up with them. So does only taking one class and investing
ridiculous amounts of time on the homework.)

Thanks again for helping me avoid C.

Now to write some "thinning" code...

--kyler
Jul 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
2304
by: Gary Stephenson | last post by:
I'm getting a clean generate, compile and link from my .pyx script, but when I attempt to run the resultant .exe, I get: "The procedure entry point Py_NoneStruct could not be located in the dynamic link library python23.dll" Can anybody provide me with a clue here? I've already cut down my script to remove all references to None, Py_None, NULLs, etc, but to no avail. fwiw I'm using latest Pyrex and ActiveState build 232.
1
1670
by: Paul Prescod | last post by:
PyCon 2004 Slides on "Extending Python with Pyrex" PDF: http://www.prescod.net/pyrex/ExtendingPythonWithPyrex.pdf PPT: http://www.prescod.net/pyrex/ExtendingPythonWithPyrex.ppt Pycon 2004 Slides on "Optimizing Python code with Pyrex" PDF: http://www.prescod.net/pyrex/OptimizingPythonWithPyrex.pdf PPT: http://www.prescod.net/pyrex/OptimizingPythonWithPyrex.ppt I hope this helps me. Please report any mistakes.
4
2071
by: Kyler Laird | last post by:
I mentioned earlier that I started using Pyrex because I'm taking a computer vision course that requires all assignments to be submitted as C(++). While I could write C it would hurt me to do so and certainly distract me from the computer vision aspects. I like using Python these days and Pyrex looked like a good solution. (BTW, on the last assignment I saw several messages from someone having difficulty with segfaults due to memory...
6
1934
by: SeeBelow | last post by:
I just read "about Pyrex" at http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/version/Doc/About.html It seems that it is not compiled into machine code, as C would be, and therefore it does not offer the only valid reason for using C, which is for an increase in execution speed. The word "speed" does not appear on the above web page. Am I wrong about this? Perhaps I don't understand how Pyrex works.
1
3576
by: Martin Bless | last post by:
Now that I've got my extension building machine using the VC++ Toolkit 2003 up and running I'm keen on using Pyrex (Pyrex-0.9.3, Python-2.4.0). But the definition of the swig_sources() method seems to have changed. When I try to build the examples from Pyrex I get a TypeError: c:\Pyrex-0.9.3\Demos> python Setup.py build_ext --inplace
7
13003
by: Pankaj | last post by:
The module which i am creating is like Part A: 1. It does some processing by using python code. 2. The result of this python code execution is written to a text file. ] Part B: 1. I read a text file which is outputted by above python script in a C++ program
27
3972
by: Julien Fiore | last post by:
Do you wand to install Pyrex on Windows ? Here is a step-by-step guide explaining: A) how to install Pyrex on Windows XP. B) how to compile a Pyrex module. Julien Fiore, U. of Geneva
11
1985
by: Jim Lewis | last post by:
Has anyone found a good link on exactly how to speed up code using pyrex? I found various info but the focus is usually not on code speedup.
7
2043
by: Jim Lewis | last post by:
I'm trying to move a function into pyrex for speed. The python side needs to pass a list to the pyrex function. Do I need to convert to array or something so pyrex can generate tight code? I'm not clear how to do this.
0
9161
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9029
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
7732
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6522
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4370
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4619
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3050
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2332
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2006
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.