]> granicus.if.org Git - python/commitdiff
Add a 'c_longdouble' type to the ctypes module.
authorThomas Heller <theller@ctypes.org>
Fri, 7 Sep 2007 06:32:17 +0000 (06:32 +0000)
committerThomas Heller <theller@ctypes.org>
Fri, 7 Sep 2007 06:32:17 +0000 (06:32 +0000)
13 files changed:
Doc/library/ctypes.rst
Lib/ctypes/__init__.py
Lib/ctypes/test/test_arrays.py
Lib/ctypes/test/test_callbacks.py
Lib/ctypes/test/test_cfuncs.py
Lib/ctypes/test/test_functions.py
Lib/ctypes/test/test_repr.py
Misc/NEWS
Modules/_ctypes/_ctypes.c
Modules/_ctypes/_ctypes_test.c
Modules/_ctypes/callproc.c
Modules/_ctypes/cfield.c
Modules/_ctypes/ctypes.h

index 6c9dbf8ad44de63b1e6599589ac6ea6df83bbdd0..a5d4a48991714277ba692440a6ca39816b4822b6 100644 (file)
@@ -249,6 +249,8 @@ Fundamental data types
    +----------------------+--------------------------------+----------------------------+
    | :class:`c_double`    | ``double``                     | float                      |
    +----------------------+--------------------------------+----------------------------+
+   | :class:`c_longdouble`| ``long double``                | float                      |
+   +----------------------+--------------------------------+----------------------------+
    | :class:`c_char_p`    | ``char *`` (NUL terminated)    | string or ``None``         |
    +----------------------+--------------------------------+----------------------------+
    | :class:`c_wchar_p`   | ``wchar_t *`` (NUL terminated) | unicode or ``None``        |
@@ -2067,6 +2069,13 @@ These are the fundamental ctypes data types:
    initializer.
 
 
+.. class:: c_longdouble
+
+   Represents the C long double datatype. The constructor accepts an
+   optional float initializer.  On platforms where ``sizeof(long
+   double) == sizeof(double)`` it is an alias to :class:`c_double`.
+
+
 .. class:: c_float
 
    Represents the C float datatype. The constructor accepts an optional float
index 8ab84ac380eea60265a4692d7d99555583f0369c..3ad3161dd90165875668676ec2dfbd088c5d582c 100644 (file)
@@ -191,6 +191,11 @@ class c_double(_SimpleCData):
     _type_ = "d"
 _check_size(c_double)
 
+class c_longdouble(_SimpleCData):
+    _type_ = "D"
+if sizeof(c_longdouble) == sizeof(c_double):
+    c_longdouble = c_double
+
 if _calcsize("l") == _calcsize("q"):
     # if long and long long have the same size, make c_longlong an alias for c_long
     c_longlong = c_long
index a68ef614978972f9f559dfbcd5baaa3dd58e140c..e635ae1741d84306d2a7b119d5f12112b0e4b80c 100644 (file)
@@ -4,7 +4,7 @@ from ctypes import *
 formats = "bBhHiIlLqQfd"
 
 formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \
-          c_long, c_ulonglong, c_float, c_double
+          c_long, c_ulonglong, c_float, c_double, c_longdouble
 
 class ArrayTestCase(unittest.TestCase):
     def test_simple(self):
index f47fc37b3f025089b30db505dc3034ad5a400a60..e3e4be8a287110e83d19cb6d723506c8bc07fc5b 100644 (file)
@@ -77,6 +77,10 @@ class Callbacks(unittest.TestCase):
         self.check_type(c_double, 3.14)
         self.check_type(c_double, -3.14)
 
+    def test_longdouble(self):
+        self.check_type(c_longdouble, 3.14)
+        self.check_type(c_longdouble, -3.14)
+
     def test_char(self):
         self.check_type(c_char, "x")
         self.check_type(c_char, "a")
index fa858a66132f689b4966a032ef3b40c4ba899841..724100646a3255472ed67fbd099bdabc2a17359a 100644 (file)
@@ -158,6 +158,18 @@ class CFunctions(unittest.TestCase):
         self.failUnlessEqual(self._dll.tf_bd(0, 42.), 14.)
         self.failUnlessEqual(self.S(), 42)
 
+    def test_longdouble(self):
+        self._dll.tf_D.restype = c_longdouble
+        self._dll.tf_D.argtypes = (c_longdouble,)
+        self.failUnlessEqual(self._dll.tf_D(42.), 14.)
+        self.failUnlessEqual(self.S(), 42)
+
+    def test_longdouble_plus(self):
+        self._dll.tf_bD.restype = c_longdouble
+        self._dll.tf_bD.argtypes = (c_byte, c_longdouble)
+        self.failUnlessEqual(self._dll.tf_bD(0, 42.), 14.)
+        self.failUnlessEqual(self.S(), 42)
+
     def test_callwithresult(self):
         def process_result(result):
             return result * 2
index 12bd59c4d45fe8f5247eb4b6c1516875106c9a18..93d895b42cda4d420c37e3db3726b1951037b80d 100644 (file)
@@ -143,6 +143,18 @@ class FunctionTestCase(unittest.TestCase):
         self.failUnlessEqual(result, -21)
         self.failUnlessEqual(type(result), float)
 
+    def test_longdoubleresult(self):
+        f = dll._testfunc_D_bhilfD
+        f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_longdouble]
+        f.restype = c_longdouble
+        result = f(1, 2, 3, 4, 5.0, 6.0)
+        self.failUnlessEqual(result, 21)
+        self.failUnlessEqual(type(result), float)
+
+        result = f(-1, -2, -3, -4, -5.0, -6.0)
+        self.failUnlessEqual(result, -21)
+        self.failUnlessEqual(type(result), float)
+
     def test_longlongresult(self):
         try:
             c_longlong
index f6f93666502516dd0f8b8b7e277a605e95a0ca64..9fef21ff464b55552a6b2e547fe8ded20e180d45 100644 (file)
@@ -4,7 +4,7 @@ import unittest
 subclasses = []
 for base in [c_byte, c_short, c_int, c_long, c_longlong,
         c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong,
-        c_float, c_double, c_bool]:
+        c_float, c_double, c_longdouble, c_bool]:
     class X(base):
         pass
     subclasses.append(X)
index 1963a145d0b89b8d3918504ca9a5c6c1af18bb70..99e4f07131efe75761e74f7976f094cf513e3601 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -249,6 +249,8 @@ Core and builtins
 Library
 -------
 
+- A 'c_longdouble' type was added to the ctypes module.
+
 - Bug #1709599: Run test_1565150 only if the file system is NTFS.
 
 - When encountering a password-protected robots.txt file the RobotFileParser
index 4c7c8968c7058e2378c6ca366603182c1aafeb02..3b2c72a4ed4d4d2a07d318eaf44116d837e161ff 100644 (file)
@@ -1101,7 +1101,7 @@ _type_ attribute.
 
 */
 
-static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOvt";
+static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOvtD";
 
 static PyObject *
 c_wchar_p_from_param(PyObject *type, PyObject *value)
index 5cedd19a78f9832a25f2d762c269b224e0c308fc..0d47740916299015f05c480ae196042c98a03395 100644 (file)
 
 /* some functions handy for testing */
 
+EXPORT(long double)testfunc_Ddd(double a, double b)
+{
+       long double result = (long double)(a * b);
+       printf("testfunc_Ddd(%p, %p)\n", &a, &b);
+       printf("testfunc_Ddd(%g, %g)\n", a, b);
+       return result;
+}
+
+EXPORT(long double)testfunc_DDD(long double a, long double b)
+{
+       long double result = a * b;
+       printf("testfunc_DDD(%p, %p)\n", &a, &b);
+       printf("testfunc_DDD(%Lg, %Lg)\n", a, b);
+       return result;
+}
+
+EXPORT(int)testfunc_iii(int a, int b)
+{
+       int result = a * b;
+       printf("testfunc_iii(%p, %p)\n", &a, &b);
+       return result;
+}
+
 EXPORT(int)myprintf(char *fmt, ...)
 {
        int result;
@@ -90,6 +113,14 @@ EXPORT(double) _testfunc_d_bhilfd(signed char b, short h, int i, long l, float f
        return (double)(b + h + i + l + f + d);
 }
 
+EXPORT(long double) _testfunc_D_bhilfD(signed char b, short h, int i, long l, float f, long double d)
+{
+/*     printf("_testfunc_d_bhilfd got %d %d %d %ld %f %f\n",
+              b, h, i, l, f, d);
+*/
+       return (long double)(b + h + i + l + f + d);
+}
+
 EXPORT(char *) _testfunc_p_p(void *s)
 {
        return (char *)s;
@@ -404,6 +435,7 @@ EXPORT(PY_LONG_LONG) tf_q(PY_LONG_LONG c) { S; return c/3; }
 EXPORT(unsigned PY_LONG_LONG) tf_Q(unsigned PY_LONG_LONG c) { U; return c/3; }
 EXPORT(float) tf_f(float c) { S; return c/3; }
 EXPORT(double) tf_d(double c) { S; return c/3; }
+EXPORT(long double) tf_D(long double c) { S; return c/3; }
 
 #ifdef MS_WIN32
 EXPORT(signed char) __stdcall s_tf_b(signed char c) { S; return c/3; }
@@ -418,6 +450,7 @@ EXPORT(PY_LONG_LONG) __stdcall s_tf_q(PY_LONG_LONG c) { S; return c/3; }
 EXPORT(unsigned PY_LONG_LONG) __stdcall s_tf_Q(unsigned PY_LONG_LONG c) { U; return c/3; }
 EXPORT(float) __stdcall s_tf_f(float c) { S; return c/3; }
 EXPORT(double) __stdcall s_tf_d(double c) { S; return c/3; }
+EXPORT(long double) __stdcall s_tf_D(long double c) { S; return c/3; }
 #endif
 /*******/
 
@@ -433,6 +466,7 @@ EXPORT(PY_LONG_LONG) tf_bq(signed char x, PY_LONG_LONG c) { S; return c/3; }
 EXPORT(unsigned PY_LONG_LONG) tf_bQ(signed char x, unsigned PY_LONG_LONG c) { U; return c/3; }
 EXPORT(float) tf_bf(signed char x, float c) { S; return c/3; }
 EXPORT(double) tf_bd(signed char x, double c) { S; return c/3; }
+EXPORT(long double) tf_bD(signed char x, long double c) { S; return c/3; }
 EXPORT(void) tv_i(int c) { S; return; }
 
 #ifdef MS_WIN32
@@ -448,6 +482,7 @@ EXPORT(PY_LONG_LONG) __stdcall s_tf_bq(signed char x, PY_LONG_LONG c) { S; retur
 EXPORT(unsigned PY_LONG_LONG) __stdcall s_tf_bQ(signed char x, unsigned PY_LONG_LONG c) { U; return c/3; }
 EXPORT(float) __stdcall s_tf_bf(signed char x, float c) { S; return c/3; }
 EXPORT(double) __stdcall s_tf_bd(signed char x, double c) { S; return c/3; }
+EXPORT(long double) __stdcall s_tf_bD(signed char x, long double c) { S; return c/3; }
 EXPORT(void) __stdcall s_tv_i(int c) { S; return; }
 #endif
 
index 80d6dffb397766e3f7aa20b101e80eb3fc682869..7a69e21b3901281912f2a27cf45e4efb0f542657 100644 (file)
@@ -449,6 +449,7 @@ union result {
 #ifdef HAVE_LONG_LONG
        PY_LONG_LONG q;
 #endif
+       long double D;
        double d;
        float f;
        void *p;
index 0e4c19e2d942968ef5da6b0c63e798ccd5afaacf..872a6eee0eb0eebb05380abfe1a46e0be7532f5d 100644 (file)
@@ -5,6 +5,7 @@
 #include "Python.h"
 
 #include <ffi.h>
+#include <fficonfig.h>
 #ifdef MS_WIN32
 #include <windows.h>
 #endif
@@ -989,6 +990,29 @@ Q_get_sw(void *ptr, Py_ssize_t size)
  */
 
 
+static PyObject *
+D_set(void *ptr, PyObject *value, Py_ssize_t size)
+{
+       long double x;
+
+       x = PyFloat_AsDouble(value);
+       if (x == -1 && PyErr_Occurred()) {
+               PyErr_Format(PyExc_TypeError,
+                            " float expected instead of %s instance",
+                            value->ob_type->tp_name);
+               return NULL;
+       }
+       memcpy(ptr, &x, sizeof(long double));
+       _RET(value);
+}
+
+static PyObject *
+D_get(void *ptr, Py_ssize_t size)
+{
+       long double val;
+       memcpy(&val, ptr, sizeof(long double));
+       return PyFloat_FromDouble(val);
+}
 
 static PyObject *
 d_set(void *ptr, PyObject *value, Py_ssize_t size)
@@ -1584,6 +1608,7 @@ static struct fielddesc formattable[] = {
        { 'B', B_set, B_get, &ffi_type_uchar},
        { 'c', c_set, c_get, &ffi_type_schar},
        { 'd', d_set, d_get, &ffi_type_double, d_set_sw, d_get_sw},
+       { 'D', D_set, D_get, &ffi_type_longdouble},
        { 'f', f_set, f_get, &ffi_type_float, f_set_sw, f_get_sw},
        { 'h', h_set, h_get, &ffi_type_sshort, h_set_sw, h_get_sw},
        { 'H', H_set, H_get, &ffi_type_ushort, H_set_sw, H_get_sw},
@@ -1666,6 +1691,7 @@ typedef struct { char c; int x; } s_int;
 typedef struct { char c; long x; } s_long;
 typedef struct { char c; float x; } s_float;
 typedef struct { char c; double x; } s_double;
+typedef struct { char c; long double x; } s_long_double;
 typedef struct { char c; char *x; } s_char_p;
 typedef struct { char c; void *x; } s_void_p;
 
@@ -1677,6 +1703,8 @@ typedef struct { char c; void *x; } s_void_p;
 */
 #define FLOAT_ALIGN (sizeof(s_float) - sizeof(float))
 #define DOUBLE_ALIGN (sizeof(s_double) - sizeof(double))
+#define LONGDOUBLE_ALIGN (sizeof(s_long_double) - sizeof(long double))
+
 /* #define CHAR_P_ALIGN (sizeof(s_char_p) - sizeof(char*)) */
 #define VOID_P_ALIGN (sizeof(s_void_p) - sizeof(void*))
 
@@ -1722,6 +1750,8 @@ ffi_type ffi_type_sint64 = { 8, LONG_LONG_ALIGN, FFI_TYPE_SINT64 };
 
 ffi_type ffi_type_float = { sizeof(float), FLOAT_ALIGN, FFI_TYPE_FLOAT };
 ffi_type ffi_type_double = { sizeof(double), DOUBLE_ALIGN, FFI_TYPE_DOUBLE };
+ffi_type ffi_type_longdouble = { sizeof(long double), LONGDOUBLE_ALIGN,
+                                FFI_TYPE_LONGDOUBLE };
 
 /* ffi_type ffi_type_longdouble */
 
index bf2bdaa6ffc6eddb5e846e2923fb010617855168..b6f23821e5bc665e3edfe92688d6d5178f4ee809 100644 (file)
@@ -47,6 +47,7 @@ union value {
 #ifdef HAVE_LONG_LONG
                PY_LONG_LONG ll;
 #endif
+               long double D;
 };
 
 /*
@@ -300,6 +301,7 @@ struct tagPyCArgObject {
 #ifdef HAVE_LONG_LONG
                PY_LONG_LONG q;
 #endif
+               long double D;
                double d;
                float f;
                void *p;