This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author gholling
Recipients gholling, theller
Date 2009-04-06.17:28:40
SpamBayes Score 2.0359342e-10
Marked as misclassified No
Message-id <1239038926.27.0.792638874347.issue5710@psf.upfronthosting.co.za>
In-reply-to
Content
We have an application that calls a 3rd party library that returns a
structure (by value) from a callback.  I'm including some sample code
that duplicates the behavior.  The problem is that return types from
callbacks cannot be anything other than simple datatypes (c_int,
c_float, ..., c_void_p).  For other datatypes (STRUCTURE, POINTER, ...),
ctypes returns the following error:

"invalid result type for callback function"

The error message comes from callback.c, in function AllocFunctionCallback.

I think this may be a duplicate of issue #1574584.

I've tested this on Windows and linux; I'm including a Makefile and
source code that works on Windows/cygwin.

------ file: Makefile ----

all: hello.dll hello.exe hello_dll.exe
clean: 
	rm *.exe *.dll

hello.exe: hello.h hello.c hello_main.c
	gcc hello.c hello_main.c -o hello.exe --save-temps

hello.dll: hello.h hello.c
	gcc -mno-cygwin -shared hello.c -o hello.dll --save-temps

hello_dll.exe: hello.h hello.c
	gcc hello_main.c -L. -lhello -o hello_main.exe

------ file: hello.h ----
struct helloStruct {
  int i;
  float f;
  int i2;
  int i3;
};

float fxn (struct  helloStruct callback());

------ file: hello.c ----

#include <stdio.h> 
#include "hello.h"

float fxn (struct helloStruct callback()) {
  struct  helloStruct result = callback();

  printf ("i: %d\n", result.i);
  printf ("f: %f\n", result.f);
  return result.f * result.i;
}

------ file: hello_main.c ----

#include <stdio.h> 
#include "hello.h"

struct helloStruct callback();

int main (int argc, char **argv) {
  float f;
  struct helloStruct result;
  printf ("Hello world\n");
  f = fxn (callback);
  printf ("Callback result: %f\n", f);
}

struct helloStruct callback () {
  struct helloStruct result;
  result.i = 10;
  result.f = 3.14159;
  return result;
}

int int_callback () {
  return 42;
}

------ file: hello.py ----

from ctypes import cdll, c_char, c_int, c_float, Structure, CFUNCTYPE,
POINTER, c_char_p

class helloStruct (Structure):
    pass
helloStruct._fields_ = [
    ('i', c_int),
    ('f', c_float)    ]

def callback():
    print ("callback()")
    hs = helloStruct()
    hs.i = 10
    hs.f = 25.5
    return hs

libc = cdll.msvcrt
#helloLib = libc.load_library("hello")
#helloLib = libc.hello
helloLib = cdll.hello

helloLib.fxn.restype = helloStruct
# It looks like only simple return types are supported for
# callback functions.  simple = c_int, c_float, ...
# Python bug # 1574584 - status: closed.
#    Suggests posting to ctypes-users, but I don't see any recent activity.
#
TMP_FCN = CFUNCTYPE (POINTER(c_char))           # Error message
#TMP_FCN = CFUNCTYPE (c_char_p)                  # Runs, but invalid result
#TMP_FCN = CFUNCTYPE (c_void_p)                  # Runs, but invalid result
#TMP_FCN = CFUNCTYPE (c_int)                  # Runs, but invalid result
#TMP_FCN = CFUNCTYPE (POINTER(c_int))         # Error message
#TMP_FCN = CFUNCTYPE (POINTER(helloStruct))   # Error message
#TMP_FCN = CFUNCTYPE (helloStruct)            # Error message
callback_fcn = TMP_FCN (callback)
result = helloLib.fxn (callback_fcn)

# 2.5
#print "result: ", result
# 3.0
print ("result: ", result)
History
Date User Action Args
2009-04-06 17:28:47ghollingsetrecipients: + gholling, theller
2009-04-06 17:28:46ghollingsetmessageid: <1239038926.27.0.792638874347.issue5710@psf.upfronthosting.co.za>
2009-04-06 17:28:43ghollinglinkissue5710 messages
2009-04-06 17:28:41ghollingcreate