summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Heller <theller@ctypes.org>2007-09-07 06:32:17 (GMT)
committerThomas Heller <theller@ctypes.org>2007-09-07 06:32:17 (GMT)
commit2825b2ea444e3ce03cac7fc562fe6b7166972459 (patch)
tree418a77753ce23a6520adec24ed4294f51ed786d5
parent1e534b5425d836cb58a73d24f0be791d67bf3503 (diff)
downloadcpython-2825b2ea444e3ce03cac7fc562fe6b7166972459.zip
cpython-2825b2ea444e3ce03cac7fc562fe6b7166972459.tar.gz
cpython-2825b2ea444e3ce03cac7fc562fe6b7166972459.tar.bz2
Add a 'c_longdouble' type to the ctypes module.
-rw-r--r--Doc/library/ctypes.rst9
-rw-r--r--Lib/ctypes/__init__.py5
-rw-r--r--Lib/ctypes/test/test_arrays.py2
-rw-r--r--Lib/ctypes/test/test_callbacks.py4
-rw-r--r--Lib/ctypes/test/test_cfuncs.py12
-rw-r--r--Lib/ctypes/test/test_functions.py12
-rw-r--r--Lib/ctypes/test/test_repr.py2
-rw-r--r--Misc/NEWS2
-rw-r--r--Modules/_ctypes/_ctypes.c2
-rw-r--r--Modules/_ctypes/_ctypes_test.c35
-rw-r--r--Modules/_ctypes/callproc.c1
-rw-r--r--Modules/_ctypes/cfield.c30
-rw-r--r--Modules/_ctypes/ctypes.h2
13 files changed, 115 insertions, 3 deletions
diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst
index 6c9dbf8..a5d4a48 100644
--- a/Doc/library/ctypes.rst
+++ b/Doc/library/ctypes.rst
@@ -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
diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py
index 8ab84ac..3ad3161 100644
--- a/Lib/ctypes/__init__.py
+++ b/Lib/ctypes/__init__.py
@@ -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
diff --git a/Lib/ctypes/test/test_arrays.py b/Lib/ctypes/test/test_arrays.py
index a68ef61..e635ae1 100644
--- a/Lib/ctypes/test/test_arrays.py
+++ b/Lib/ctypes/test/test_arrays.py
@@ -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):
diff --git a/Lib/ctypes/test/test_callbacks.py b/Lib/ctypes/test/test_callbacks.py
index f47fc37..e3e4be8 100644
--- a/Lib/ctypes/test/test_callbacks.py
+++ b/Lib/ctypes/test/test_callbacks.py
@@ -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")
diff --git a/Lib/ctypes/test/test_cfuncs.py b/Lib/ctypes/test/test_cfuncs.py
index fa858a6..7241006 100644
--- a/Lib/ctypes/test/test_cfuncs.py
+++ b/Lib/ctypes/test/test_cfuncs.py
@@ -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
diff --git a/Lib/ctypes/test/test_functions.py b/Lib/ctypes/test/test_functions.py
index 12bd59c..93d895b 100644
--- a/Lib/ctypes/test/test_functions.py
+++ b/Lib/ctypes/test/test_functions.py
@@ -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
diff --git a/Lib/ctypes/test/test_repr.py b/Lib/ctypes/test/test_repr.py
index f6f9366..9fef21f 100644
--- a/Lib/ctypes/test/test_repr.py
+++ b/Lib/ctypes/test/test_repr.py
@@ -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)
diff --git a/Misc/NEWS b/Misc/NEWS
index 1963a14..99e4f07 100644
--- 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
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 4c7c896..3b2c72a 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -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)
diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c
index 5cedd19..0d47740 100644
--- a/Modules/_ctypes/_ctypes_test.c
+++ b/Modules/_ctypes/_ctypes_test.c
@@ -25,6 +25,29 @@
/* 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
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index 80d6dff..7a69e21 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -449,6 +449,7 @@ union result {
#ifdef HAVE_LONG_LONG
PY_LONG_LONG q;
#endif
+ long double D;
double d;
float f;
void *p;
diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c
index 0e4c19e..872a6ee 100644
--- a/Modules/_ctypes/cfield.c
+++ b/Modules/_ctypes/cfield.c
@@ -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 */
diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h
index bf2bdaa..b6f2382 100644
--- a/Modules/_ctypes/ctypes.h
+++ b/Modules/_ctypes/ctypes.h
@@ -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;