<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.pymol.org/index.php?action=history&amp;feed=atom&amp;title=Advanced_Scripting</id>
	<title>Advanced Scripting - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.pymol.org/index.php?action=history&amp;feed=atom&amp;title=Advanced_Scripting"/>
	<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Advanced_Scripting&amp;action=history"/>
	<updated>2026-07-05T21:00:36Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Advanced_Scripting&amp;diff=4178&amp;oldid=prev</id>
		<title>Pyadmin: 15 revisions</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Advanced_Scripting&amp;diff=4178&amp;oldid=prev"/>
		<updated>2014-03-28T01:31:01Z</updated>

		<summary type="html">&lt;p&gt;15 revisions&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left diff-editfont-monospace&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 01:31, 28 March 2014&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Pyadmin</name></author>
	</entry>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Advanced_Scripting&amp;diff=4177&amp;oldid=prev</id>
		<title>Pavel: /* More Complex Unpacking */</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Advanced_Scripting&amp;diff=4177&amp;oldid=prev"/>
		<updated>2013-05-08T20:47:23Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;More Complex Unpacking&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left diff-editfont-monospace&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 20:47, 8 May 2013&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l89&quot; &gt;Line 89:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 89:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Now, we should have access to the data the user sent us, in '''listA''' and '''listB,''' and it should be there and be clean.  But, not forgetting that '''listA''' and '''listB''' are list of 3D coordinates, let's unpack them further into sets of coordinates.  Because we know the length of the lists, we can do something like the following:&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Now, we should have access to the data the user sent us, in '''listA''' and '''listB,''' and it should be there and be clean.  But, not forgetting that '''listA''' and '''listB''' are list of 3D coordinates, let's unpack them further into sets of coordinates.  Because we know the length of the lists, we can do something like the following:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;source lang=&amp;quot;c&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;&amp;quot; line=&amp;quot;1&lt;/del&gt;&amp;quot;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;        // make space for the current coords; pcePoint is just a float[3]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;        // make space for the current coords; pcePoint is just a float[3]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;        pcePoint coords = (pcePoint) malloc(sizeof(cePoint)*length);&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;        pcePoint coords = (pcePoint) malloc(sizeof(cePoint)*length);&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l120&quot; &gt;Line 120:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 121:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;  ... more code ...&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;  ... more code ...&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/source&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/source&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Where, '''pcePoint''' is just a float[3].  Line 2 just gets some memory ready for the 3xlenght list of coordinates.  Then, for each item for 1..length, we unpack the list using '''[http://docs.python.org/api/listObjects.html PyList_GetItem]''', into '''curCoord'''.  This then gets further unpacked into the float[3], '''coords'''.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Where, '''pcePoint''' is just a float[3].  Line 2 just gets some memory ready for the 3xlenght list of coordinates.  Then, for each item for 1..length, we unpack the list using '''[http://docs.python.org/api/listObjects.html PyList_GetItem]''', into '''curCoord'''.  This then gets further unpacked into the float[3], '''coords'''.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Pavel</name></author>
	</entry>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Advanced_Scripting&amp;diff=4176&amp;oldid=prev</id>
		<title>Pavel: /* Unpacking the Data */</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Advanced_Scripting&amp;diff=4176&amp;oldid=prev"/>
		<updated>2013-05-08T20:46:44Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Unpacking the Data&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;On this page, we discuss more complex scripting.  Python is great, but it is much slower at mathematics than C/C++/Java/FORTRAN.  For that reason, you may find it more useful to export your data to another language, operate on it there and then import the results back into PyMOL.  We discuss the Python API and the general operating procedure for successfully writing your own scripts.&lt;br /&gt;
&lt;br /&gt;
= Advanced Scripting =&lt;br /&gt;
Python while incredibly useful, is much slower at math than some other strictly typed languages and sometimes we have libraries built in other languages.  It's faster, for complicated problems to package your data, send it to C, do some math, and pass the results back to Python than to just do everything in Python.  The beauty of the Python API, is that we can do just that.&lt;br /&gt;
&lt;br /&gt;
This is more advanced scripting, and requires some knowledge of the [http://docs.python.org/api/api.html Python API], and some outside language.  The example shown here is in C.  The C++ extensions are very similar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Python, PyMOL and C ===&lt;br /&gt;
Here, I will show you how to write a C-module that plugs into Python and talks nicely with PyMOL.  The example actually shows how to make a generic C-function and use it in Python.&lt;br /&gt;
&lt;br /&gt;
First, let's assume that we want to call a function, let's call it '''funName'''.  Let's assume '''funName''' will take a Python list of lists and return a list---for example passing the C++ program the XYZ coordinates of each atom, and returning a list of certain atoms with some property.  I will also assume we have '''funName.h''' and '''funName.c''' for C code files.  I have provided this, a more complex example, to show a real-world problem.  If you were just sending an integer or float instead of packaged lists, the code is simpler; if you understand unpacking the lists then you'll certainly understand unpacking a simple scalar.&lt;br /&gt;
&lt;br /&gt;
===== C++ =====&lt;br /&gt;
If you tell Python that you're using C++ code (see the setup below) then it'll automatically call the C++ compiler instead of the C compiler.  There are [http://docs.python.org/ext/cplusplus.html warnings] you may want to be aware of though.&lt;br /&gt;
&lt;br /&gt;
My experience with this has been pretty easy.  I simple renamed my &amp;quot;.c&amp;quot; files to &amp;quot;.cpp&amp;quot;, caught the few errors (darn it, I didn't typecast a few pointers from malloc) and the code compiled fine.  My experience with this is also quite limited, YMMV.&lt;br /&gt;
&lt;br /&gt;
==== Calling the External Function ====&lt;br /&gt;
So, to start, let's look at the Python code that will call the C-function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# -- in someCode.py&lt;br /&gt;
#&lt;br /&gt;
# Call funName.  Pass it a list () of lists.  (sel1 and sel2 are lists.)&lt;br /&gt;
# Get the return value into rValFromC.&lt;br /&gt;
#&lt;br /&gt;
rValFromC = funName( (sel1, sel2) );&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
where '''sel1''' and '''sel2''' could be any list of atom coordinates, say, from PyMOL.  (See above.)&lt;br /&gt;
&lt;br /&gt;
Ok, this isn't hard.  Now, we need to see what the code that receives this function call in C, looks like.  Well, first we need to let C know we're integrating with Python.  So, in your [http://docs.python.org/api/includes.html header file] of '''funName.h''' we put:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// in funName.h&lt;br /&gt;
#include &amp;lt;Python.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, by default your C-function's name is '''funName_funName''' (and that needs to be setup, I'll show how, later).  So, let's define funName:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static PyObject*&lt;br /&gt;
funName_funName(PyObject* self, PyObject* args)&lt;br /&gt;
{&lt;br /&gt;
...more code...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This is the generic call.  '''funName''' is taking two pointers to [http://docs.python.org/api/common-structs.html PyObjects].  It also returns a PyObject.  This is how you get the Python data into and out of C.  It shows up in &amp;quot;[http://docs.python.org/api/arg-parsing.html args]&amp;quot; array of packaged Python objects and we then unpack it into C, using some [http://docs.python.org/api/arg-parsing.html helper methods].  Upon completion of unpacking,  we perform our C/C++ procedure with the data, package up the results using the [http://docs.python.org/api/api.html Python API], and send the results back to Python/PyMOL.&lt;br /&gt;
&lt;br /&gt;
==== Unpacking the Data ====&lt;br /&gt;
Let's unpack the data in '''args'''.  Remember, '''args''' has a Python [http://docs.python.org/lib/typesseq.html list of lists].  So, to unpack that we do the following inside of funName:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static PyObject*&lt;br /&gt;
funName_funName(PyObject* self, PyObject* args)&lt;br /&gt;
{&lt;br /&gt;
       PyObject *listA, *listB;&lt;br /&gt;
&lt;br /&gt;
       if ( ! PyArg_ParseTuple(args, &amp;quot;(OO)&amp;quot;, &amp;amp;listA, &amp;amp;listB) ) {&lt;br /&gt;
                printf(&amp;quot;Could not unparse objects\n&amp;quot;);&lt;br /&gt;
                return NULL;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // let Python know we made two lists&lt;br /&gt;
        Py_INCREF(listA);&lt;br /&gt;
        Py_INCREF(listB);&lt;br /&gt;
 ... more code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Line 4 creates the two C objects that we will unpack the lists into.  They are pointers to PyObjects.&lt;br /&gt;
Line 6 is where the magic happens.  We call, '''[http://docs.python.org/api/arg-parsing.html PyArg_ParseTuple]''' passing it the args we got from Python.  The '''(OO)''' is Python's code for ''I'm expecting two &amp;lt;u&amp;gt;O&amp;lt;/u&amp;gt;bjects inside a list &amp;lt;u&amp;gt;()&amp;lt;/u&amp;gt;''.  Were it three objects, then '''(OOO)'''.  The first object will be put into '''&amp;amp;listA''' and the second into '''&amp;amp;listB'''.  The exact [http://docs.python.org/api/arg-parsing.html argument building specifications] are very useful.&lt;br /&gt;
&lt;br /&gt;
==== Reference Counting ====&lt;br /&gt;
Next, we check for success.  Unpacking could fail.  If it does, complain and quit.  Else, '''listA''' and '''listB''' now have data in them.  To avoid memory leaks we need to [http://docs.python.org/api/countingRefs.html manually keep track of PyObjects] we're tooling around with.  That is, I can create PyObjects in C (being sneaky and not telling Python) and then when Python quits later on, it'll not know it was supposed to clean up after those objects (making a leak).  To, we let Python know about each list with '''Py_INCREF(listA)''' and '''Py_INCREF(listB)'''.  This is [http://docs.python.org/api/countingRefs.html reference counting].&lt;br /&gt;
&lt;br /&gt;
Now, just for safety, let's check the lists to make sure they actually were passed something.  A tricky user could have given us empty lists, looking to hose the program.  So, we do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
     // handle empty selections (should probably do this in Python, it's easier)&lt;br /&gt;
     const int lenA = PyList_Size(listA);&lt;br /&gt;
     if ( lenA &amp;lt; 1 ) {&lt;br /&gt;
             printf(&amp;quot;ERROR: First selection didn't have any atoms.  Please check your selection.\n&amp;quot;);&lt;br /&gt;
             // let Python remove the lists&lt;br /&gt;
             Py_DECREF(listA);&lt;br /&gt;
             Py_DECREF(listB);&lt;br /&gt;
             return NULL;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
We check the list size with, '''[http://docs.python.org/api/listObjects.html PyList_Size]''' and if it's 0 -- we quit.  But, before quitting we give control of the lists back to Python so it can clean up after itself.  We do that with '''Py_DECREF'''.&lt;br /&gt;
&lt;br /&gt;
==== More Complex Unpacking ====&lt;br /&gt;
If you're dealing with simple scalars, then you might be able to skip this portion.&lt;br /&gt;
&lt;br /&gt;
Now, we should have access to the data the user sent us, in '''listA''' and '''listB,''' and it should be there and be clean.  But, not forgetting that '''listA''' and '''listB''' are list of 3D coordinates, let's unpack them further into sets of coordinates.  Because we know the length of the lists, we can do something like the following:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
       // make space for the current coords; pcePoint is just a float[3]&lt;br /&gt;
       pcePoint coords = (pcePoint) malloc(sizeof(cePoint)*length);&lt;br /&gt;
&lt;br /&gt;
       // loop through the arguments, pulling out the&lt;br /&gt;
       // XYZ coordinates.&lt;br /&gt;
       int i;&lt;br /&gt;
       for ( i = 0; i &amp;lt; length; i++ ) {&lt;br /&gt;
               PyObject* curCoord = PyList_GetItem(listA,i);&lt;br /&gt;
               Py_INCREF(curCoord);&lt;br /&gt;
       &lt;br /&gt;
               PyObject* curVal = PyList_GetItem(curCoord,0);&lt;br /&gt;
               Py_INCREF(curVal);&lt;br /&gt;
               coords[i].x = PyFloat_AsDouble(curVal);&lt;br /&gt;
               Py_DECREF(curVal);&lt;br /&gt;
&lt;br /&gt;
               curVal = PyList_GetItem(curCoord,1);&lt;br /&gt;
               Py_INCREF(curVal);&lt;br /&gt;
               coords[i].y = PyFloat_AsDouble(curVal);&lt;br /&gt;
               Py_DECREF(curVal);&lt;br /&gt;
&lt;br /&gt;
               curVal = PyList_GetItem(curCoord,2);&lt;br /&gt;
               Py_INCREF(curVal);&lt;br /&gt;
               coords[i].z = PyFloat_AsDouble(curVal);&lt;br /&gt;
               Py_DECREF(curVal);&lt;br /&gt;
&lt;br /&gt;
               Py_DECREF(curCoord);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
 ... more code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Where, '''pcePoint''' is just a float[3].  Line 2 just gets some memory ready for the 3xlenght list of coordinates.  Then, for each item for 1..length, we unpack the list using '''[http://docs.python.org/api/listObjects.html PyList_GetItem]''', into '''curCoord'''.  This then gets further unpacked into the float[3], '''coords'''.&lt;br /&gt;
&lt;br /&gt;
We now have the data in C++/C data structures that the user passed from PyMOL.  Now, perform your task in C/C++ and then return the data to PyMOL.&lt;br /&gt;
&lt;br /&gt;
=== Sending the Results back to Python/PyMOL ===&lt;br /&gt;
Once you're done with your calculations and want to send your data back to PyMOL, you need to package it up into a Python object, using the Python API, and then return it.  You should be aware of the expected return value and how you're packaging the results.  If you user calls,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
(results1,results2) = someCFunction(parameters1,parameters2)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
then you need to package a list with two values.  To build values for returning to PyMOL, use '''[http://www.python.org/doc/1.5.2p2/ext/buildValue.html Py_BuildValue]'''.  Py_BuildValue takes a string indicating the type, and then a list of values.  [http://docs.python.org/ext/buildValue.html Building values] for return has been documented very well.  Consider an example: if I want to package an array of integers, the type specifier for two ints for Py_BuildValue is, &amp;quot;[i,i]&amp;quot;, so my call could be:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
# Package the two ints into a Python pair of ints.&lt;br /&gt;
PyObject* thePair = Py_BuildValue( &amp;quot;[i,i]&amp;quot;, int1, in2 );&lt;br /&gt;
&lt;br /&gt;
# Don't forget to tell Python about the object.&lt;br /&gt;
Py_INCREF(thePair);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need to make a list of things to return, you iterate through a list and make a bunch of '''thePairs''' and add them to a Python list as follows:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
# Make the python list&lt;br /&gt;
PyObject* theList = PyList_New(0);&lt;br /&gt;
# Tell Python about it&lt;br /&gt;
Py_INCREF(theList);&lt;br /&gt;
&lt;br /&gt;
for ( int i = 0; i &amp;lt; someLim; i++ ) {&lt;br /&gt;
  PyObject* thePair = Py_BuildValue( &amp;quot;[i,i]&amp;quot;, int1, in2 );&lt;br /&gt;
  Py_INCREF(thePair);&lt;br /&gt;
  PyList_Append(theList,thePair);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
To add a list of lists, just make an outer list, &amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;PyObject* outerList = PyList_New(0);&amp;lt;/source&amp;gt; and iteratively add to it your inner lists:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
PyObject* outerList = PyList_New(0);&lt;br /&gt;
Py_INCREF(outerList);&lt;br /&gt;
&lt;br /&gt;
for ( int i = 0; i &amp;lt; someLim; i++ ) {&lt;br /&gt;
  // make the inner list, called curList;&lt;br /&gt;
  curList = PyObject* curList = PyList_New(0);&lt;br /&gt;
  Py_INCREF(curList);&lt;br /&gt;
&lt;br /&gt;
  // fill the inner list, using PyList_Append with some data, shown above&lt;br /&gt;
  ...&lt;br /&gt;
&lt;br /&gt;
  PyList_Append(outerList,curList);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Great, now we can extract data from Python, use it in C/C++, and package it back up for returning to Python.  Now, we need to learn about the minimal baggage needed for C to operate with Python.  Keep reading; almost done.&lt;br /&gt;
&lt;br /&gt;
=== Initialization ===&lt;br /&gt;
We need to discuss how our functions will be called from Python.  First, we need to create a [http://docs.python.org/ext/methodTable.html method table].&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static PyMethodDef CEMethods[] = {&lt;br /&gt;
        {&amp;quot;ccealign&amp;quot;, ccealign_ccealign, METH_VARARGS, &amp;quot;Align two proteins using the CE Algorithm.&amp;quot;},&lt;br /&gt;
        {NULL, NULL, 0, NULL}     /* Always use this as the last line in your table. */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''[http://docs.python.org/ext/methodTable.html METH_VARARGS]''' can also be '''METH_KEYWORDS''', where the former tells C that it should expect a simple tuple or list which we will unpack with '''PyArg_ParseTuple''', and the latter tells C that it should expect to unpack the variables by name&lt;br /&gt;
with the '''PyArg_ParseTupleAndKeywords'''.  When using '''METH_KEYWORDS''' your function needs to accept a third parameter, a '''Py_Object*''' that is the dictionary of names for unpacking.  For more information check out the [http://docs.python.org/ext/methodTable.html Python method table docs].&lt;br /&gt;
&lt;br /&gt;
Each module undergoes initialization.  By default the modules initialization function is: '''initNAME()'''.  So, in our example above, '''initccealign()&amp;quot;.  During this initialization step, we need to call [http://docs.python.org/ext/methodTable.html Py_InitModule].  For or above example, we'd have,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
PyMODINIT_FUNC&lt;br /&gt;
initccealign(void)&lt;br /&gt;
{&lt;br /&gt;
    (void) Py_InitModule(&amp;quot;ccealign&amp;quot;, CEMethods);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, the main function that starts the whole shebang should look something like:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int&lt;br /&gt;
main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
        Py_SetProgramName(argv[0]);&lt;br /&gt;
        Py_Initialize();&lt;br /&gt;
        initccealign();&lt;br /&gt;
        return(EXIT_SUCCESS);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point, you should have a fully functioning program in C/C++ intergrated with PyMOL/Python.&lt;br /&gt;
&lt;br /&gt;
=== Installing Your Module ===&lt;br /&gt;
==== Overview ====&lt;br /&gt;
The [http://www.python.org/doc/2.2.3/ext/distributing.html Python distutils pacakge] is a great method for distributing your modules over various platforms.  It handles platform specific issues as well as simplifying the overall install process.  For us, those module-builders, we need to create the distuils' setup.py script, and given the above -- that's the last step.&lt;br /&gt;
&lt;br /&gt;
More detailed information can be found one the Python documentation page for [http://docs.python.org/ext/building.html installing C/C++ modules].  There is also information on [http://www.python.org/doc/2.2.3/ext/distributing.html how to build source and binary distribution packages].  &lt;br /&gt;
&lt;br /&gt;
For example of how powerful disutils is, I have [cealign] setup to install as simply as:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
python setup.py build cealign&lt;br /&gt;
python setup.py install cealign&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
PyMOL also uses distutils for it's source-install.  If more people understood distutils, I think they would install PyMOL from source since you get all the latest features.&lt;br /&gt;
&lt;br /&gt;
==== Setup.py ====&lt;br /&gt;
The setup file needs to know the following (at the very least): what source files comprise the project, what include directories to scan, the project name.  You can also add more metadata such as version number, author, author_email, url, etc.  For this example, let's assume we have the following directory structure,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
.&lt;br /&gt;
|-- build&lt;br /&gt;
|-- dist&lt;br /&gt;
|-- doc&lt;br /&gt;
|   `-- funName&lt;br /&gt;
|-- src&lt;br /&gt;
|   |-- etc&lt;br /&gt;
|   |   `-- tnt&lt;br /&gt;
|   |       |-- doxygen&lt;br /&gt;
|   |       |   `-- html&lt;br /&gt;
|   |       `-- html&lt;br /&gt;
|   `-- tnt&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
and we want to include all the ''.cpp'' files from the '''src''' directory, and all the include files in '''tnt'''.  We start setup.py as follows,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# -- setup.py -- your module's install file&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
# import distutils&lt;br /&gt;
from distutils.core import setup, Extension&lt;br /&gt;
# for pasting together file lists&lt;br /&gt;
from glob import glob&lt;br /&gt;
# for handling path names in a os independent way&lt;br /&gt;
from os.path import join;&lt;br /&gt;
&lt;br /&gt;
# grab all of the .h and .cpp files in src/ and src/tnt&lt;br /&gt;
srcList = [ x for x in glob(join(&amp;quot;src&amp;quot;, &amp;quot;*.cpp&amp;quot;)) ]&lt;br /&gt;
# set the include directories&lt;br /&gt;
incDirs = [ join( &amp;quot;src&amp;quot;, &amp;quot;tnt&amp;quot;) ]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ok, now Python knows which files to include.  Now we need to create a new [http://docs.python.org/dist/module-distutils.extension.html Extension].  We can simply call,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# create the extension given the function name, ''funName,'' the souce list and include directories.&lt;br /&gt;
ccealignMods = Extension( 'funName', sources=srcList, include_dirs=incDirs  )&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lastly, all we have to do is call the final setup function, with the extension we just created and some metadata (if we want):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
setup( name=&amp;quot;funName&amp;quot;,&lt;br /&gt;
        version=&amp;quot;0.1-alpha&amp;quot;,&lt;br /&gt;
        description=&amp;quot;funName: A simple example to show users how to make C/C++ modules for PyMOL&amp;quot;,&lt;br /&gt;
        author=&amp;quot;Your Name Here&amp;quot;,&lt;br /&gt;
        author_email=&amp;quot;Your Email Goes Here&amp;quot;,&lt;br /&gt;
        url=&amp;quot;The URL of your work&amp;quot;,&lt;br /&gt;
        ext_modules=[ccealignMods]&lt;br /&gt;
         )&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And voila -- we're done.  The users should now be able to execute,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
python setup.py build&lt;br /&gt;
# remove the brackets if you need to be root to install, see [Linux_Install#Installing_a_Script_Without_Superuser_Access Installing PyMOL w/o Superuser access] for an example.&lt;br /&gt;
[sudo] python setup.py install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
* discuss the pains of debugging&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
I hope you found this helpful and will spur you to actually write some PyMOL modules or help you overcome the speed limitations inherent in Python's math (in comparison to other strictly-typed languages).&lt;br /&gt;
&lt;br /&gt;
I'm happy to hear any comments or questions you may have.  [[User:Inchoate|Tree]] 09:14, 19 May 2008 (CDT)&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
See the source code for [[cealign]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
[[stored]], [[iterate_state]], [[identify]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting|Advanced_Scripting]]&lt;br /&gt;
[[Category:Development|Advanced_Scripting]]&lt;br /&gt;
[[Category:Tutorials|Advanced_Scripting]]&lt;/div&gt;</summary>
		<author><name>Pavel</name></author>
	</entry>
</feed>