11import ctypes .util
22
3+ # This file contains C-API bindings based on the objectbox.h, linking to the 'objectbox' shared library
4+
35# initialize the C library
46C = ctypes .CDLL (ctypes .util .find_library ("objectbox" ))
57
@@ -40,6 +42,9 @@ class OBX_store_options(ctypes.Structure):
4042 ('maxReaders' , ctypes .c_uint )
4143 ]
4244
45+ def p (self ) -> 'ctypes.POINTER(OBX_store_options)' :
46+ return ctypes .pointer (self )
47+
4348
4449OBX_store_options_p = ctypes .POINTER (OBX_store_options )
4550
@@ -108,33 +113,77 @@ class OBX_query(ctypes.Structure):
108113
109114OBX_query_p = ctypes .POINTER (OBX_query )
110115
116+ # manually configure error methods, we can't use `fn()` defined bellow yet due to circular dependencies
117+ C .obx_last_error_message .restype = ctypes .c_char_p
118+ C .obx_last_error_code .restype = obx_err
119+
111120
112121class CError (Exception ):
122+ codes = {
123+ 0 : "SUCCESS" ,
124+ 404 : "NOT_FOUND" ,
125+ 10001 : "ILLEGAL_STATE" ,
126+ 10002 : "ILLEGAL_ARGUMENT" ,
127+ 10003 : "ALLOCATION" ,
128+ 10097 : "NO_ERROR_INFO" ,
129+ 10098 : "GENERAL" ,
130+ 10099 : "UNKNOWN" ,
131+ 10101 : "DB_FULL" ,
132+ 10102 : "MAX_READERS_EXCEEDED" ,
133+ 10103 : "STORE_MUST_SHUTDOWN" ,
134+ 10199 : "STORAGE_GENERAL" ,
135+ 10201 : "UNIQUE_VIOLATED" ,
136+ 10202 : "NON_UNIQUE_RESULT" ,
137+ 10203 : "PROPERTY_TYPE_MISMATCH" ,
138+ 10299 : "CONSTRAINT_VIOLATED" ,
139+ 10301 : "STD_ILLEGAL_ARGUMENT" ,
140+ 10302 : "STD_OUT_OF_RANGE" ,
141+ 10303 : "STD_LENGTH" ,
142+ 10304 : "STD_BAD_ALLOC" ,
143+ 10305 : "STD_RANGE" ,
144+ 10306 : "STD_OVERFLOW" ,
145+ 10399 : "STD_OTHER" ,
146+ 10501 : "SCHEMA" ,
147+ 10502 : "FILE_CORRUPT"
148+ }
149+
113150 def __init__ (self , code ):
114151 self .code = code
115- self .message = ctypes . c_char_p (C .obx_last_error_message ()). value . decode ( "utf8" )
116- super (CError , self ).__init__ (self .message )
152+ self .message = py_str (C .obx_last_error_message ())
153+ super (CError , self ).__init__ ("%d (%s) - %s" % ( code , self .codes [ code ], self . message ) )
117154
118155
119156# check obx_err and raise an error
120- def errcheck (code : obx_err , func , args ):
157+ def check_obx_err (code : obx_err , func , args ):
121158 if code != 0 :
122159 raise CError (code )
123160
124161
162+ # check if the returned pointer is null and raise an error
163+ def check_ptr_result (result , func , args ):
164+ if not result :
165+ raise CError (C .obx_last_error_code ())
166+ return result
167+
168+
125169# creates a global function "name" with the given restype & argtypes, calling C function with the same name
126170def fn (name : str , restype : type , argtypes ):
127171 func = C .__getattr__ (name )
128172
129- if restype == obx_err :
130- func .errcheck = errcheck
131- else :
173+ if restype is obx_err :
174+ func .errcheck = check_obx_err
175+ elif restype is not None :
176+ func .errcheck = check_ptr_result
132177 func .restype = restype
133178
134179 func .argtypes = argtypes
135180 return func
136181
137182
183+ def py_str (ptr : ctypes .c_char_p ) -> str :
184+ return ctypes .c_char_p (ptr ).value .decode ("utf-8" )
185+
186+
138187def c_str (string : str ) -> ctypes .c_char_p :
139188 return string .encode ('utf-8' )
140189
@@ -149,6 +198,28 @@ def c_str(string: str) -> ctypes.c_char_p:
149198obx_model_property = fn ('obx_model_property' , obx_err ,
150199 [OBX_model_p , ctypes .c_char_p , OBXPropertyType , obx_schema_id , obx_uid ])
151200
201+ # obx_err (OBX_model* model, OBXPropertyFlags flags);
202+ obx_model_property_flags = fn ('obx_model_property_flags' , obx_err , [OBX_model_p , OBXPropertyFlags ])
203+
204+ # obx_err (OBX_model*, obx_schema_id entity_id, obx_uid entity_uid);
205+ obx_model_last_entity_id = fn ('obx_model_last_entity_id' , obx_err , [OBX_model_p , obx_schema_id , obx_uid ])
206+
207+ # obx_err (OBX_model* model, obx_schema_id index_id, obx_uid index_uid);
208+ obx_model_last_index_id = fn ('obx_model_last_index_id' , obx_err , [OBX_model_p , obx_schema_id , obx_uid ])
209+
210+ # obx_err (OBX_model* model, obx_schema_id relation_id, obx_uid relation_uid);
211+ obx_model_last_relation_id = fn ('obx_model_last_relation_id' , obx_err , [OBX_model_p , obx_schema_id , obx_uid ])
212+
213+ # obx_err (OBX_model* model, obx_schema_id property_id, obx_uid property_uid);
214+ obx_model_entity_last_property_id = fn ('obx_model_entity_last_property_id' , obx_err ,
215+ [OBX_model_p , obx_schema_id , obx_uid ])
216+
217+ # OBX_store* (OBX_model* model, const OBX_store_options* options);
218+ obx_store_open = fn ('obx_store_open' , OBX_store_p , [OBX_model_p , OBX_store_options_p ])
219+
220+ # obx_err (OBX_store* store);
221+ obx_store_close = fn ('obx_store_close' , obx_err , [OBX_store_p ])
222+
152223OBXPropertyType_Bool = 1
153224OBXPropertyType_Byte = 2
154225OBXPropertyType_Short = 3
@@ -184,7 +255,6 @@ def c_str(string: str) -> ctypes.c_char_p:
184255OBXDebugFlags_LOG_QUERY_PARAMETERS = 8 ,
185256OBXDebugFlags_LOG_ASYNC_QUEUE = 16 ,
186257
187-
188258# Standard put ("insert or update")
189259OBXPutMode_PUT = 1 ,
190260
@@ -198,7 +268,6 @@ def c_str(string: str) -> ctypes.c_char_p:
198268# This is primarily used internally. Wrong usage leads to inconsistent data (e.g. index data not updated)!
199269OBXPutMode_PUT_ID_GUARANTEED_TO_BE_NEW = 4
200270
201-
202271# Reverts the order from ascending (default) to descending.
203272OBXOrderFlags_DESCENDING = 1 ,
204273
0 commit comments