I'm trying to pass an pointer to an enum. I found a tutorial for ctypes and enum here [ctypes structures ][1] but my application is a little different. the pseudocode for my DLL looks like this
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#ifdef SOME_API_EXPORTS
#define SOME_API __declspec(dllexport)
#else
#define SOME_API __declspec(dllimport)
#endif
typedef enum
{
off,
on
} MyEnum;
SOME_API int32_t get_param(MyEnum* param1)
{
int status = error;
if (param1 == NULL)
{
return status;
}
//do some processing
status = done;
return status;
}
what I did in python looks similar to this:
import ctypes
from enum import IntEnum
test = ctypes.WinDLL('Project.dll')
if (test == 0):
print( " Could not open DLL")
class CtypesEnum(IntEnum):
@classmethod
def from_param(cls, obj):
return int(obj)
class myEnum(CtypesEnum):
off = 0
on = 1
getParam = test.get_param
getParam.argtypes = [ctypes.POINTER(ctypes.c_int)]
getParam.restype= ctypes.c_uint
getParam(myEnum.on)
The error I get now is
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
getParam(myEnum.on)
ctypes.ArgumentError: argument 1: <class 'TypeError'>: expected LP_c_long instance instead of myEnum
What's the correct way of passing an enum pointer using ctypes.I couldn't find an example and I'm kinda new to python :/
[1]: https://v4.chriskrycho.com/2015/ctypes-structures-and-dll-exports.html
This was my solution for the python part. I read 1 and 0 respectively.
import ctypes
from ctypes import *
test = ctypes.WinDLL('Project.dll')
if (test == 0):
print( " Could not open DLL")
class myEnum(c_int):
off = 0
on = 1
getParam = test.get_param
getParam.argtype = myEnum()
getParam.restype= ctypes.c_int
result = test.get_param(myEnum.on)
print(result)
result = test.get_param(myEnum.off)
print(result)
Listing [Python.Docs]: ctypes - A foreign function library for Python.
As I stated in my comment, the 1st error is (most likely) the same thing as [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer), then after the edit, another one (which occurs before the 1st) pops up.
Here's how to get rid of all.
dll00.c:
#include <stdio.h>
#include <stdint.h>
#if defined(_WIN32)
# define DLL00_EXPORT_API __declspec(dllexport)
#else
# define DLL00_EXPORT_API
#endif
typedef enum {
Off,
On,
} Enum;
#if defined(__cplusplus)
extern "C" {
#endif
DLL00_EXPORT_API int32_t get_param(Enum *pparam);
#if defined(__cplusplus)
}
#endif
int32_t get_param(Enum *pparam) {
int status = -1;
if (pparam == NULL) {
printf("NULL arg\n");
return status;
}
printf("C - arg: %d\n", *pparam);
if (pparam == NULL) {
return status;
}
//do some processing
status = 1;
return status;
}
code00.py:
#!/usr/bin/env python
import sys
import ctypes as ct
from enum import IntEnum
DLL_NAME = "./dll00.{:s}".format("dll" if sys.platform[:3].lower() == "win" else "so")
class CtypesEnum(IntEnum):
@classmethod
def from_param(cls, obj):
return int(obj)
class OOEnum(CtypesEnum):
Off = 0
On = 1
def main(*argv):
dll = ct.CDLL(DLL_NAME) # Use ct.WinDLL for Win 32bit
get_param = dll.get_param
get_param.argtypes = (ct.POINTER(ct.c_int),)
get_param.restype = ct.c_int
for en in [
OOEnum.Off,
OOEnum.On,
]:
get_param(ct.pointer(ct.c_int(en.value)))
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)
Output:
[cfati@cfati-5510-0:/mnt/e/Work/Dev/StackOverflow/q068826175]> ~/sopr.sh ### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ### [064bit prompt]> ls code00.py dll00.c [064bit prompt]> [064bit prompt]> gcc -shared -m64 -fPIC -o dll00.so dll00.c [064bit prompt]> ls code00.py dll00.c dll00.so [064bit prompt]> [064bit prompt]> ${PY_VENVS_HOME}/py_pc064_03_08_test0/bin/python code00.py Python 3.8.10 (default, Jun 2 2021, 10:49:15) [GCC 9.4.0] 064bit on linux C - arg: 0 C - arg: 1 Done.
Things are the same on Win, only build (and run) commands differ.