From 1b92b8690920e5e31bf37589fb4cf854fa06c9e1 Mon Sep 17 00:00:00 2001 From: Carl Fischer Date: Fri, 15 Jun 2012 11:47:47 -0400 Subject: [PATCH 1/8] Almost functional Linux builds. --- setup.py | 2 +- spicemodule_custom.c | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index 8a9ce6b..29eaf34 100644 --- a/setup.py +++ b/setup.py @@ -100,7 +100,7 @@ def set_build_paths(): libraries = ['cspice'], include_dirs=[os.path.join(CSPICE_SRC, 'include'),], library_dirs=[os.path.join(CSPICE_SRC, 'lib'),], - define_macros=[('MSDOS', None), + define_macros=[#('MSDOS', None), ('_COMPLEX_DEFINED', None), ('OMIT_BLANK_CC', None)], ) diff --git a/spicemodule_custom.c b/spicemodule_custom.c index 37f8991..0a510c3 100644 --- a/spicemodule_custom.c +++ b/spicemodule_custom.c @@ -122,19 +122,28 @@ PyObject * spice_getelm(PyObject *self, PyObject *args) // How to properly allocate memory?? Am I allowed to use malloc? // See: http://article.gmane.org/gmane.comp.python.general/424736 - f_lines = (char*) PyMem_Malloc(2+line1_len+line2_len); + f_lines = (char*) PyMem_Malloc(5+line1_len+line2_len); + + if (f_lines == NULL) { + printf("Tried to allocate %d bytes\n", 5+line1_len+line2_len); + return PyErr_NoMemory(); + } + + // Offset to the start of the second line. - lineln = line1_len+1; + lineln = line1_len+2; // Add 1 to line_len to be sure we copy the null too. - strncpy(f_lines, line1, line1_len+1); - strncpy(f_lines+lineln, line2, line2_len+1); - + printf("About to do strncopying.\n"); + strncpy(f_lines, line1, line1_len+2); + printf("One down, one to go!\n"); + strncpy(f_lines+lineln, line2, line2_len+2); + printf("Done strncopying.\n"); getelm_c(firstyr, lineln, f_lines, &epoch, elems); - + PyMem_Free(f_lines); PYSPICE_CHECK_FAILED; - + if(failed) { return NULL; } From 70ef31228e906e838667445b14242a8df1dee2fd Mon Sep 17 00:00:00 2001 From: Carl4 Date: Tue, 26 Jun 2012 22:16:10 -0400 Subject: [PATCH 2/8] first cut at a windows compatible version --- mkprodct_cspice.bat | 76 ++++++++++ spicemodule_custom.c | 330 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 406 insertions(+) create mode 100644 mkprodct_cspice.bat create mode 100644 spicemodule_custom.c diff --git a/mkprodct_cspice.bat b/mkprodct_cspice.bat new file mode 100644 index 0000000..8d972d6 --- /dev/null +++ b/mkprodct_cspice.bat @@ -0,0 +1,76 @@ +rem +rem mkcspice.bat Adapted to build cspice under windows / msys +rem +rem Creates cspice.lib for MS Visual C++ and moves it to the +rem appropriate Toolkit directory. +rem +rem +rem Version 3.1.0 19-OCT-2003 (BVS) +rem +rem added -DNON_ANSI_STDIO compile option. +rem +rem Version 3.0.0 03-NOV-1999 (NJB) +rem +rem fixed the last "set cl" command. +rem +rem Version 2.0.0 26-FEB-1999 (NJB) +rem +rem Added OMIT_BLANK_CC preprocessor flag. +rem +rem Version 1.0.0 29-DEC-1998 (NJB) +rem + +cd cspice\src\cspice + +set cl= /c /O2 -D_COMPLEX_DEFINED -DMSDOS -DOMIT_BLANK_CC -DNON_ANSI_STDIO + +rem +rem The optimization algorithm has a very tough time with zzsecptr.c, +rem so exempt this routine from optimization. +rem + +rename zzsecprt.c zzsecprt.x + +rem +rem Compile everything else. +rem + +REM BEGIN FISCHER MOD +REM for %%f in (*.c) do cl %%f +gcc -I..\..\include -c -O2 -D_COMPLEX_DEFINED -DOMIT_BLANK_CC -DNON_ANSI_STDIO -DMSDOS *.c +REM ENDFISCHERMOD + +rem +rem Set the cl variable to omit optimization. Compile zzsecprt.c. +rem + + +REM BEGIN FISCHER MOD +REM set cl= /c -D_COMPLEX_DEFINED -DMSDOS -DOMIT_BLANK_CC +REM END + +rename zzsecprt.x zzsecprt.c + +REM BEGIN FISCHER MOD +REM cl zzsecprt.c +gcc -I..\..\include -c -D_COMPLEX_DEFINED -DOMIT_BLANK_CC -DMSDOS zzsecprt.c +REM END + +dir /b *.o > temp.lst + +REM BEGIN FISCHER MOD +REM link -lib /out:cspice.lib @temp.lst + +REM gcc -o cspice.lib @temp.lst +ar -cq cspice.lib @temp.lst +gcc -shared -o cspice.dll @temp.lst +REM END FISCHER MOD + + +move cspice.lib ..\..\lib +move cspice.dll ..\..\lib + + +rem del *.o +del temp.lst + diff --git a/spicemodule_custom.c b/spicemodule_custom.c new file mode 100644 index 0000000..d0cb94f --- /dev/null +++ b/spicemodule_custom.c @@ -0,0 +1,330 @@ +/* + * spicemodule_cust.om.c + * + * Created on: Jun 24, 2012 + * Author: Daddy + */ + +#include "pyspice.h" +#include + +PyObject *SpiceException; + +/* void spkw10_c ( SpiceInt handle,SpiceInt body,SpiceInt center, +ConstSpiceChar * frame,SpiceDouble first,SpiceDouble last, +ConstSpiceChar * segid,ConstSpiceDouble consts [8],SpiceInt n, +ConstSpiceDouble elems [],ConstSpiceDouble epochs [] ); */ +static PyObject * spice_spkw10(PyObject *self, PyObject *args) +{ + /* variables for inputs */ + long handle; + long body; + long center; + char * frame; + double first; + double last; + char * segid; + double consts[8]; + long n; + PyObject * elems; + PyObject * epochs; + PyObject * elem_seq; + PyObject * epoch_seq; + PyObject * elem; + int i, j ; + double * c_elems; + double * c_epochs; + + char failed = 0; + + PYSPICE_CHECK_RETURN_STATUS(PyArg_ParseTuple(args, "lllsdds(dddddddd)OO", + &handle, &body, ¢er, &frame, &first, &last, &segid, + &consts[0], &consts[1], &consts[2], &consts[3], &consts[4], + &consts[5], &consts[6], &consts[7], &elems, &epochs)); + + // This will fail. Allocation and translation for elems and epoch. + //spkw10_c(handle, body, center, frame, first, last, segid, consts, n, &elems, &epochs); + /* Need to do the following: + * 1: Allocate memory for elems and epochs + * 2: Populate elems and epochs from the python iterables that get passed in. + */ + elem_seq = PySequence_Fast(elems, "expected a sequence for elems"); + epoch_seq = PySequence_Fast(epochs, "expected a sequence for epochs"); + + n = PySequence_Size(elem_seq); + if (n != PySequence_Size(epoch_seq)) { + // TODO: How to raise an exception?? + printf("Naa na naa na naa\nNa na naa na naa\nYou're gonna _____! "); + return NULL; + } + // How to properly allocate memory?? Am I allowed to use malloc? + // See: http://article.gmane.org/gmane.comp.python.general/424736 + c_elems = (double*) PyMem_Malloc(n * 10 * sizeof(double)); + c_epochs = (double*) PyMem_Malloc(n * sizeof(double)); + + for (i = 0; i < n; i++) { + c_epochs[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(epoch_seq, i)); + elem = PySequence_Fast_GET_ITEM(elem_seq, i); + + for (j = 0 ; j < 10 ; j++) { + c_elems[i*10+j] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(elem, j)); + } + + /* DON'T DECREF item here */ + //Py_DECREF(elem); + //Py_DECREF(epoch); + } + + Py_DECREF(elem_seq); + Py_DECREF(epoch_seq); + + spkw10_c(handle, body, center, frame, first, last, segid, consts, n, + c_elems, c_epochs); + + PyMem_Free(c_elems); + PyMem_Free(c_epochs); + + PYSPICE_CHECK_FAILED; + + if(failed) { + return NULL; + } + + + Py_INCREF(Py_None); + return Py_None; +} +PyDoc_STRVAR(spkw10_doc, "-Abstract\n\n Write an SPK type 10 segment to the DAF open and attached to\n the input handle.\n\n-Brief_I/O\n\n VARIABLE I/O DESCRIPTION\n -------- --- --------------------------------------------------\n handle I The handle of a DAF file open for writing.\n body I The NAIF ID code for the body of the segment.\n center I The center of motion for body.\n frame I The reference frame for this segment.\n first I The first epoch for which the segment is valid.\n last I The last epoch for which the segment is valid.\n segid I The string to use for segment identifier.\n consts I The array of geophysical constants for the segment\n # REMOVED: n I The number of element/epoch pairs to be stored\n elems I The collection of \"two-line\" element sets.\n epochs I The epochs associated with the element sets.\n\n-Detailed_Output\n\n None. The data input is stored in an SPK segment in the\n DAF connected to the input handle.\n\n"); + +/* void getelm_c ( SpiceInt frstyr, + SpiceInt lineln, + const void * lines, + SpiceDouble * epoch, + SpiceDouble * elems ) */ +static PyObject * spice_getelm(PyObject *self, PyObject *args) +{ + /* variables for inputs */ + long firstyr; + long lineln; + long line1_len, line2_len; + char * line1; + char * line2; + char * f_lines; + + double elems[10]; + double epoch; + + char failed = 0; + + PYSPICE_CHECK_RETURN_STATUS(PyArg_ParseTuple(args, "l(s#s#)", + &firstyr, &line1, &line1_len, &line2, &line2_len)); + + // How to properly allocate memory?? Am I allowed to use malloc? + // See: http://article.gmane.org/gmane.comp.python.general/424736 + f_lines = (char*) PyMem_Malloc(2+line1_len+line2_len); + // Offset to the start of the second line. + lineln = line1_len+1; + // Add 1 to line_len to be sure we copy the null too. + strncpy(f_lines, line1, line1_len+1); + strncpy(f_lines+lineln, line2, line2_len+1); + + getelm_c(firstyr, lineln, f_lines, &epoch, elems); + + PyMem_Free(f_lines); + + PYSPICE_CHECK_FAILED; + + if(failed) { + return NULL; + } + + PyObject *returnVal = Py_BuildValue("d(dddddddddd)", epoch,\ + elems[0], elems[1], elems[2],\ + elems[3], elems[4], elems[5],\ + elems[6], elems[7], elems[8],\ + elems[9] ); + return returnVal; + + + Py_INCREF(Py_None); + return Py_None; +} +PyDoc_STRVAR(getelm_doc, "-Brief_I/O\ + \ + VARIABLE I/O DESCRIPTION\ + -------- --- --------------------------------------------------\ + frstyr I Year of earliest representable two-line elements.\ + lineln I Length of strings in lines array.\ + lines I A pair of ''lines'' containing two-line elements.\ + epoch O The epoch of the elements in seconds past J2000. \ + elems O The elements converted to SPICE units.\ +\ +-Detailed_Input\ +\ + frstyr is the first year possible for two line elements. Since\ + two line elements allow only two digits for the year, some\ + conventions must be followed concerning which century the\ + two digits refer to. frstyr is the year of the earliest\ + representable elements. The two-digit year is mapped to\ + the year in the interval from frstyr to frstyr + 99 that\ + has the same last two digits as the two digit year in the\ + element set. For example if frstyr is set to 1960 then\ + the two digit years are mapped as shown in the table\ + below:\ +\ + Two-line Maps to\ + element year\ +\ + 00 2000\ + 01 2001\ + 02 2002\ + . .\ + . .\ + . .\ + 58 2058 \ + 59 2059\ + -------------------- \ + 60 1960\ + 61 1961\ + 62 1962\ + . .\ + . .\ + . .\ + 99 1999 \ +\ + Note that if Space Command should decide to represent\ + years in 21st century as 100 + the last two digits of the\ + year (for example: 2015 is represented as 115) instead of\ + simply dropping the first two digits of the year, this\ + routine will correctly map the year as long as you set\ + frstyr to some value between 1900 and 1999.\ +\ + lines is a pair of lines of text that comprise a Space command\ + ``two-line element'' set. lines should be declared\ +\ + SpiceChar lines[2][lineln];\ +\ + These text lines should be the same as they are presented\ + in the two-line element files available from Space\ + Command (formerly NORAD). Below is an example of a\ + two-line set for TOPEX.\ +\ + TOPEX\ + 1 22076U 92052A 97173.53461370 -.00000038 00000-0 10000-3 0 594\ + 2 22076 66.0378 163.4372 0008359 278.7732 81.2337 12.80930736227550\ +\ +\ +\ +\ +-Detailed_Output\ +\ + epoch is the epoch of the two line elements supplied via\ + the input array lines. Epoch is returned in TDB\ + seconds past J2000.\ +\ + elems is an array containing the elements from the two line\ + set supplied via the array lines. The elements are\ + in units suitable for use by the CSPICE routine\ + ev2lin_. \ +\ + Also note that the elements XNDD6O and BSTAR\ + incorporate the exponential factor present in the\ + input two line elements in LINES. (See particulars\ + below.\ +\ + ELEMS [ 0 ] = XNDT2O in radians/minute**2\ + ELEMS [ 1 ] = XNDD6O in radians/minute**3\ + ELEMS [ 2 ] = BSTAR\ + ELEMS [ 3 ] = XINCL in radians\ + ELEMS [ 4 ] = XNODEO in radians\ + ELEMS [ 5 ] = EO\ + ELEMS [ 6 ] = OMEGAO in radians\ + ELEMS [ 7 ] = XMO in radians\ + ELEMS [ 8 ] = XNO in radians/minute\ + ELEMS [ 9 ] = EPOCH of the elements in seconds\ + past ephemeris epoch J2000.\ +\ +-Parameters\ +\ + None.\ +\ +-Exceptions\ +\ + No checking of the inputs is performed in this routine. However, this\ + routine does call other CSPICE routines. If one of these routines\ + detects an error it will diagnose it and signal an error.\ +\ +-Files\ +\ + You must have loaded a SPICE leapseconds kernel into the\ + kernel pool prior to caling this routine.\ +\ +-Particulars\ +\ + This routine parses a Space Command Two-line element set and returns\ + the orbital elements properly scaled and in units suitable for use\ + by other SPICE software. Input elements look like the following\ +\ +---------------------------------------------------------------------\ +1 22076U 92052A 97173.53461370 -.00000038 00000-0 10000-3 0 594\ +2 22076 66.0378 163.4372 0008359 278.7732 81.2337 12.80930736227550\ +---------------------------------------------------------------------\ +^\ +123456789012345678901234567890123456789012345678901234567890123456789\ + 1 2 3 4 5 6\ +\ + The ``raw'' elements in the first and second lines are marked below.\ + Note that in several instances exponents and decimal points are\ + implied. Also note that input units are degrees, degrees/day**n and\ + revolutions/day.\ +\ +\ + DAY OF YEAR NDD60 BSTAR\ + vvvvvvvvvvvv vvvvvv vvvvvv \ +---------------------------------------------------------------------\ +1 22076U 92052A 97173.53461370 -.00000038 00000-0 10000-3 0 594\ +---------------------------------------------------------------------\ + ^^ ^^^^^^^^^^ ^^ ^^\ + YEAR NDT20 IEXP IBEXP\ +\ +\ +\ + The ``raw'' elements in the second line are marked below\ + NODE0 OMEGA N0\ + vvvvvvvv vvvvvvvv vvvvvvvvvvv\ +---------------------------------------------------------------------\ +2 22076 66.0378 163.4372 0008359 278.7732 81.2337 12.80930736227550\ +---------------------------------------------------------------------\ + ^^^^^^^^ ^^^^^^^ ^^^^^^^^\ + Inclination Eccentricity M0\ +\ + This routine extracts these values ``inserts'' the implied\ + decimal points and exponents and then converts the inputs\ + to units of radians, radians/minute, radians/minute**2, and\ + radians/minute**3"); + +/* +PyMethodDef custom_methods[] = { + {"spkw10", spice_spkw10, METH_VARARGS, spkw10_doc}, + {"getelm", spice_getelm, METH_VARARGS, getelm_doc}, + {NULL, NULL}, + +}; + + +void init_spice(PyObject *self) +{ + PyObject *m = NULL; + + m = Py_InitModule("_spice", custom_methods); + + // on't allow an exception to stop execution + erract_c("SET", 0, "RETURN"); + errdev_c("SET", 0, "NULL"); + + SpiceException = PyErr_NewException("_spice.SpiceException", PyExc_Exception, NULL); + Py_INCREF(SpiceException); + + PyModule_AddObject(m, "SpiceException", SpiceException); +} +*/ From d19ba05ea5e18b24a46908746b44be49d8245ae0 Mon Sep 17 00:00:00 2001 From: Carl4 Date: Tue, 26 Jun 2012 23:20:56 -0400 Subject: [PATCH 3/8] Works with Enthought Python Distribution 7.3, 64-bit windows, using MSYS. Added spicemodule_custom.c and spicemodule_custom.h --- mkwrapper.py | 70 +++++++++++++++++++++++++++----------------- pyspice.h | 2 ++ setup.py | 38 ++++++++++++++++++++---- spicemodule_custom.c | 5 ++-- spicemodule_custom.h | 9 ++++++ 5 files changed, 89 insertions(+), 35 deletions(-) create mode 100644 spicemodule_custom.h diff --git a/mkwrapper.py b/mkwrapper.py index 2f38905..fb3eb9e 100644 --- a/mkwrapper.py +++ b/mkwrapper.py @@ -84,6 +84,9 @@ def __setattr__(self, key, val): 'gfevnt_c', 'gffove_c', 'gfocce_c', 'gfuds_c', 'uddc_c', 'uddf_c', ) +custom_list = ('spkw10_c', 'getelm_c', + ) + module_defs = [] cspice_src = None @@ -200,8 +203,9 @@ def get_doc(function_name): return '"%s"' % doc.getvalue() -def gen_wrapper(prototype, buffer): - prototype = remove_extra_spaces(prototype) +def gen_function(prototype_obj, prototype_comment, python_function_name, buffer): + # declare the function for this wrapper + manually_build_returnVal = False input_list = [] input_name_list = [] @@ -216,37 +220,12 @@ def gen_wrapper(prototype, buffer): # likely STRING_LEN above). string_output_num = 0 - # parse up the given prototype into its fundamental pieces. this function - # returns a container object with all the information parsed up. - prototype_obj = parse_prototype(prototype) - - # check the exclude list before continuing - if prototype_obj.function_name in exclude_list: return False # the string that is passed to PyArg_ParseTuple for getting the # arguments list and Py_BuildValue for returning results parse_tuple_string = "" buildvalue_string = "" - # remove the _c suffix for the python function name - python_function_name = prototype_obj.function_name.rsplit('_c',1)[0] - - # Add the C function prototype to the source code output. - t = '/* %s */' % prototype - prototype_comment_list = [] - while len(t) > 80: - count = 79 - while t[count-1] != ',' and count > 1: - count -= 1 - - prototype_comment_list.append(t[:count]) - t = t[count:] - if t: - prototype_comment_list.append(t) - - prototype_comment = '\n'.join(prototype_comment_list) - - # declare the function for this wrapper buffer.write( "\n%s\nstatic PyObject * spice_%s(PyObject *self, PyObject *args)\n{" % \ (prototype_comment, python_function_name)); @@ -534,7 +513,44 @@ def gen_wrapper(prototype, buffer): pass # for now; TODO: figure out what to do buffer.write("\n}"); + return python_function_name + + +def gen_wrapper(prototype, buffer): + prototype = remove_extra_spaces(prototype) + + + # parse up the given prototype into its fundamental pieces. this function + # returns a container object with all the information parsed up. + prototype_obj = parse_prototype(prototype) + + # remove the _c suffix for the python function name + python_function_name = prototype_obj.function_name.rsplit('_c',1)[0] + + + # check the exclude list before continuing + if (prototype_obj.function_name in exclude_list and + prototype_obj.function_name not in custom_list ): return False + + # Add the C function prototype to the source code output. + t = '/* %s */' % prototype + prototype_comment_list = [] + while len(t) > 80: + count = 79 + while t[count-1] != ',' and count > 1: + count -= 1 + + prototype_comment_list.append(t[:count]) + t = t[count:] + if t: + prototype_comment_list.append(t) + + prototype_comment = '\n'.join(prototype_comment_list) + + if prototype_obj.function_name not in custom_list: + gen_function(prototype_obj, prototype_comment, python_function_name, buffer, ) + # dig out the function name from the source file doc = get_doc(prototype_obj.function_name) diff --git a/pyspice.h b/pyspice.h index 5c2dbcd..4f2f3ec 100644 --- a/pyspice.h +++ b/pyspice.h @@ -12,6 +12,8 @@ #include +#include "spicemodule_custom.h" + #ifndef __PYSPICE_H__ #define __PYSPICE_H__ 1 diff --git a/setup.py b/setup.py index 3649d97..8a9ce6b 100644 --- a/setup.py +++ b/setup.py @@ -7,6 +7,9 @@ from shutil import copy from subprocess import PIPE, Popen +WINDOWS = os.sys.platform == 'win32' + + APP_NAME = os.path.basename(os.getcwd()) SHARE_DIR = os.path.join('share', 'spicedoc') @@ -28,14 +31,20 @@ class LibError(Exception): pass def build_cspice(): - libfile_path = os.path.join(CSPICE_SRC, 'lib', 'cspice.a') - if os.path.exists(libfile_path): + libfile_paths = (os.path.join(CSPICE_SRC, 'lib', 'cspice.a'), + os.path.join(CSPICE_SRC, 'lib', 'cspice.lib'), + ) + if any(os.path.exists(x) for x in libfile_paths): return curr_dir = os.getcwd() try: - os.chdir(CSPICE_SRC) - makeall = Popen('/bin/csh makeall.csh', shell=True) + if WINDOWS: + makeall = Popen('mkprodct_cspice.bat', shell=True) + + else: + os.chdir(CSPICE_SRC) + makeall = Popen('/bin/csh makeall.csh', shell=True) status = os.waitpid(makeall.pid, 0)[1] if status != 0: @@ -44,7 +53,11 @@ def build_cspice(): os.chdir(curr_dir) def find_libs(): - for libfile in ('cspice.a', 'csupport.a'): + if WINDOWS: + libfile_list = ('cspice.lib', ) + else: + libfile_list = ('cspice.a', ) + for libfile in libfile_list: libfile_path = os.path.join(CSPICE_SRC, 'lib', libfile) lib_libfile_path = os.path.join(CSPICE_SRC, 'lib', 'lib' + libfile) @@ -79,6 +92,19 @@ def set_build_paths(): path = os.path.join(CSPICE_SRC, dirname) sys.argv.append('%s%s' % (flag, path)) +spice_custom = Extension( + '_spice', + sources = ['pyspice.c', 'spicemodule.c', + 'spicemodule_custom.c' + ], + libraries = ['cspice'], + include_dirs=[os.path.join(CSPICE_SRC, 'include'),], + library_dirs=[os.path.join(CSPICE_SRC, 'lib'),], + define_macros=[('MSDOS', None), + ('_COMPLEX_DEFINED', None), + ('OMIT_BLANK_CC', None)], +) + try: build_cspice() make_spice_module() @@ -96,7 +122,7 @@ def set_build_paths(): version = '1.0', description = 'Spice Wrapper Module', packages = ['spice'], - ext_modules = [module1] + ext_modules = [spice_custom] ) finally: cleanup() diff --git a/spicemodule_custom.c b/spicemodule_custom.c index d0cb94f..37f8991 100644 --- a/spicemodule_custom.c +++ b/spicemodule_custom.c @@ -7,6 +7,7 @@ #include "pyspice.h" #include +#include "spicemodule_custom.h" PyObject *SpiceException; @@ -14,7 +15,7 @@ PyObject *SpiceException; ConstSpiceChar * frame,SpiceDouble first,SpiceDouble last, ConstSpiceChar * segid,ConstSpiceDouble consts [8],SpiceInt n, ConstSpiceDouble elems [],ConstSpiceDouble epochs [] ); */ -static PyObject * spice_spkw10(PyObject *self, PyObject *args) +PyObject * spice_spkw10(PyObject *self, PyObject *args) { /* variables for inputs */ long handle; @@ -101,7 +102,7 @@ PyDoc_STRVAR(spkw10_doc, "-Abstract\n\n Write an SPK type 10 segment to the DA const void * lines, SpiceDouble * epoch, SpiceDouble * elems ) */ -static PyObject * spice_getelm(PyObject *self, PyObject *args) +PyObject * spice_getelm(PyObject *self, PyObject *args) { /* variables for inputs */ long firstyr; diff --git a/spicemodule_custom.h b/spicemodule_custom.h new file mode 100644 index 0000000..33a59c9 --- /dev/null +++ b/spicemodule_custom.h @@ -0,0 +1,9 @@ + + +#ifndef __PYSPICE_CUSTOM_H__ +#define __PYSPICE_CUSTOM_H__ 1 + +PyObject * spice_spkw10(PyObject *self, PyObject *args); +PyObject * spice_getelm(PyObject *self, PyObject *args); + +#endif /* __PYSPICE_H__ */ From 610c5f585d5d6694f7efc5bb6480061a38f03fcf Mon Sep 17 00:00:00 2001 From: Carl4 Date: Tue, 26 Jun 2012 23:23:00 -0400 Subject: [PATCH 4/8] improved some comments. --- mkwrapper.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mkwrapper.py b/mkwrapper.py index fb3eb9e..4acfc76 100644 --- a/mkwrapper.py +++ b/mkwrapper.py @@ -528,7 +528,7 @@ def gen_wrapper(prototype, buffer): python_function_name = prototype_obj.function_name.rsplit('_c',1)[0] - # check the exclude list before continuing + # check the exclude list before continuing. if (prototype_obj.function_name in exclude_list and prototype_obj.function_name not in custom_list ): return False @@ -548,9 +548,14 @@ def gen_wrapper(prototype, buffer): prototype_comment = '\n'.join(prototype_comment_list) + # If it's not a custom command, add the function to the spicemodule.c output if prototype_obj.function_name not in custom_list: gen_function(prototype_obj, prototype_comment, python_function_name, buffer, ) + # Custom commands still get a doc string and module_defs. I tried making + # them separate modules, but the static linking of cspice meant that modules + # furnsh'd under one module were not available under the custom module. + # dig out the function name from the source file doc = get_doc(prototype_obj.function_name) From 9b604d32cb14aefbf8a8626de6284bc7ae339cf5 Mon Sep 17 00:00:00 2001 From: Carl4 Date: Tue, 26 Jun 2012 23:30:36 -0400 Subject: [PATCH 5/8] improved comments. --- mkwrapper.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkwrapper.py b/mkwrapper.py index 4acfc76..6fed28d 100644 --- a/mkwrapper.py +++ b/mkwrapper.py @@ -205,6 +205,8 @@ def get_doc(function_name): def gen_function(prototype_obj, prototype_comment, python_function_name, buffer): # declare the function for this wrapper + # I moved this block of code to a separate function for readability. It's + # still pretty cumbersome, but hey! it works. manually_build_returnVal = False input_list = [] From 20c07863113767a666e66bbd53ad2ee43e5bfbd3 Mon Sep 17 00:00:00 2001 From: Carl Fischer Date: Sun, 8 Jul 2012 05:50:12 -0400 Subject: [PATCH 6/8] Fixed an issue in Python under Linux that was preventing the memory allocation from working properly. Now compiles correctly in Linux and Winows. --- spicemodule_custom.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/spicemodule_custom.c b/spicemodule_custom.c index 37f8991..417a741 100644 --- a/spicemodule_custom.c +++ b/spicemodule_custom.c @@ -111,18 +111,28 @@ PyObject * spice_getelm(PyObject *self, PyObject *args) char * line1; char * line2; char * f_lines; + size_t bufsize; double elems[10]; double epoch; char failed = 0; - PYSPICE_CHECK_RETURN_STATUS(PyArg_ParseTuple(args, "l(s#s#)", - &firstyr, &line1, &line1_len, &line2, &line2_len)); + PYSPICE_CHECK_RETURN_STATUS(PyArg_ParseTuple(args, "l(ss)", + &firstyr, &line1, &line2)); // How to properly allocate memory?? Am I allowed to use malloc? // See: http://article.gmane.org/gmane.comp.python.general/424736 - f_lines = (char*) PyMem_Malloc(2+line1_len+line2_len); + line1_len = strlen(line1); + line2_len = strlen(line2); + + bufsize = (size_t) 2 + line1_len + line2_len; + f_lines = PyMem_Malloc(bufsize); + + if (f_lines == NULL) { + return PyErr_NoMemory(); + } + // Offset to the start of the second line. lineln = line1_len+1; // Add 1 to line_len to be sure we copy the null too. From 4319d2d6b0755e96c827c6a19c7d33f6e121fb0c Mon Sep 17 00:00:00 2001 From: Carl Fischer Date: Fri, 15 Jun 2012 11:57:01 -0400 Subject: [PATCH 7/8] Removed printf debugging lines. --- spicemodule_custom.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/spicemodule_custom.c b/spicemodule_custom.c index 1fbd09d..aa57053 100644 --- a/spicemodule_custom.c +++ b/spicemodule_custom.c @@ -136,11 +136,8 @@ PyObject * spice_getelm(PyObject *self, PyObject *args) // Offset to the start of the second line. lineln = line1_len+2; // Add 1 to line_len to be sure we copy the null too. - printf("About to do strncopying.\n"); strncpy(f_lines, line1, line1_len+2); - printf("One down, one to go!\n"); strncpy(f_lines+lineln, line2, line2_len+2); - printf("Done strncopying.\n"); getelm_c(firstyr, lineln, f_lines, &epoch, elems); PyMem_Free(f_lines); From 22874d51bb4ecab17b324c3ffde3e9634b74fe35 Mon Sep 17 00:00:00 2001 From: Carl Fischer Date: Thu, 27 Jun 2013 10:45:09 -0400 Subject: [PATCH 8/8] Updated README.rst for Windows compile instructions. --- README.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.rst b/README.rst index d13f1b1..86fa509 100644 --- a/README.rst +++ b/README.rst @@ -15,6 +15,26 @@ there, run setup.py like so:: Then install:: python setup.py install + +Windows Instructions +-------------------- + +It seems that cspice neesds to be rebuilt to work with common Windows Python +code bases. To accomplish this:: + +1. Download the cygwin gCC 32bit Windows Spice toolkit here + http://naif.jpl.nasa.gov/naif/toolkit_C.html +2. Extract the file into the PySpice folder. This will create + a cspice folder right next to spice and tests. +3. Delete cspice\lib\* We need to re-build these for your platform. +3. Run mkproduct_cspice.bat with a build environment that supports + your python distribution. If you don't do much development, but + have Enthoguht Python (EPD or Canopy), this appears to just work. +4. Run `python setup.py build_ext -c mingw32` + THE `-c mingw32` is VERY important! +5. + + 64 bit vs 32 bit ----------------