1+ import numpy
12from cffi import FFI
23import sys , re , os
34from dss_setup_common import PLATFORM_FOLDER , BUILD_ODDIE
5+ from setuptools import Extension
46
5- def process_header (src , extern_py = False , implement_py = False , prefix = '' , flags = None , fn = '' ):
7+ def process_header (src , extern_py = False , implement_py = False , prefix = '' , flags = None , fn = '' , remove = [] ):
68 '''Prepare the DSS C-API headers for parsing and building with CFFI'''
79
10+ src = src .replace ('#endif // #ifdef HAS_ALTDSS_LOADER_FUNC' , '' )
11+ src = src .replace ('#ifdef HAS_ALTDSS_LOADER_FUNC' , '' )
12+
813 if flags is not None :
914 definitions = [x [2 :] for x in flags ] # remove -D
1015 else :
1116 definitions = None
1217
1318 call_convention = '__stdcall ' if (sys .platform == 'win32' ) else ''
14-
19+
20+ for exp in remove :
21+ src = re .sub (exp , '' , src , flags = re .MULTILINE )
22+
1523 if definitions is not None :
1624 # Since we cannot easily use a C preprocessor here, some custom replacements
1725 if 'ALTDSS_USERMODEL' in definitions :
@@ -107,7 +115,7 @@ def process_header(src, extern_py=False, implement_py=False, prefix='', flags=No
107115 ))
108116
109117 src = '\n ' .join (out_lines )
110-
118+
111119 return src
112120
113121extra = {}
@@ -122,70 +130,62 @@ def process_header(src, extern_py=False, implement_py=False, prefix='', flags=No
122130src_path = os .environ .get ('SRC_DIR' , '' )
123131DSS_CAPI_PATH = os .environ .get ('DSS_CAPI_PATH' , os .path .join (src_path , '..' , 'dss_capi' ))
124132
125- VERSIONS = ['altdss_capi' , 'altdss_capid' ]
126- if BUILD_ODDIE :
127- VERSIONS .append ('altdss_oddie_capi' )
133+ ffi_builder_dss = FFI ()
134+ ffi_builders ['dss_loader' ] = ffi_builder_dss
128135
129- for version in VERSIONS :
130- ffi_builder_dss = FFI ()
131- debug = 'd' if version .endswith ('d' ) else ''
136+ # main_header_fn = os.path.join(DSS_CAPI_PATH, 'include', 'altdss', 'capi', 'dss_ctx.h')
137+ main_header_fn = os .path .join (DSS_CAPI_PATH , 'include' , 'altdss' , 'capi' , 'capi.h' )
138+ common_header_fn = os .path .join (DSS_CAPI_PATH , 'include' , 'altdss' , 'capi' , 'common.h' )
139+ enums_header_fn = os .path .join (DSS_CAPI_PATH , 'include' , 'altdss' , 'capi' , 'enums.h' )
140+ # dss_capi_ctx_path = os.path.join(DSS_CAPI_PATH, 'include', 'altdss', 'capi', 'dss_ctx.h')
141+ extra_headers = [enums_header_fn , ]
132142
133- if 'oddie' not in version :
134- main_header_fn = os .path .join (DSS_CAPI_PATH , 'include' , 'altdss' , 'capi' , 'dss_ctx.h' )
135- common_header_fn = os .path .join (DSS_CAPI_PATH , 'include' , 'altdss' , 'capi' , 'common.h' )
136- enums_header_fn = os .path .join (DSS_CAPI_PATH , 'include' , 'altdss' , 'capi' , 'enums.h' )
137- # dss_capi_ctx_path = os.path.join(DSS_CAPI_PATH, 'include', 'altdss', 'capi', 'dss_ctx.h')
138- extra_headers = [enums_header_fn , ]
139- else :
140- main_header_fn = os .path .join (DSS_CAPI_PATH , 'include' , 'altdss' , 'capi' , 'oddie.h' )
141- dss_capi_ctx_path = None
142- common_header_fn = None
143- extra_headers = []
144-
145- if common_header_fn :
146- with open (common_header_fn , 'r' ) as f :
147- cffi_header_dss = process_header (f .read (), fn = common_header_fn )
148- else :
149- cffi_header_dss = ''
143+ if common_header_fn :
144+ with open (common_header_fn , 'r' ) as f :
145+ # Remove the functions from the common header, only use the other defs
146+ cffi_header_dss = process_header (f .read (), fn = common_header_fn , remove = [r'^\s*ALTDSS_CAPI_DLL.*$' , r'^\s*HMODULE.*$' ])
147+ else :
148+ cffi_header_dss = ''
150149
151- with open (main_header_fn , 'r' ) as f :
152- cffi_header_dss += process_header (f .read (), fn = main_header_fn )
150+ with open (main_header_fn , 'r' ) as f :
151+ src = f .read ().replace ('ALTDSS_CAPI_DLL' , '' )
152+ cffi_header_dss += process_header (src , fn = main_header_fn , remove = [r'^\s*HMODULE.*$' ])
153153
154154
155- if 'oddie' not in version :
156- for extra_fn in extra_headers :
157- if os .path .exists (extra_fn ):
158- with open (extra_fn , 'r' ) as f :
159- cffi_header_dss += process_header (f .read ())
155+ for extra_fn in extra_headers :
156+ if os .path .exists (extra_fn ):
157+ with open (extra_fn , 'r' ) as f :
158+ cffi_header_dss += process_header (f .read ())
160159
161- with open ('cffi/dss_capi_custom.h' , 'r' ) as f :
162- extra_header_dss = f .read ()
163-
164- cffi_header_dss += extra_header_dss
165-
166- with open ('cffi/dss_capi_custom.c' , 'r' ) as f :
167- extra_source_dss = '#include <altdss/capi/dss_ctx.h>\n '
168- extra_source_dss += f .read ()
169- else :
170- extra_source_dss = '#include <altdss/capi/oddie.h>\n '
171-
172- ffi_builder_dss .cdef (cffi_header_dss )
173-
174- ffi_builder_dss .set_source (f"_{ version } " , extra_source_dss ,
175- libraries = [version ],
176- library_dirs = [
177- os .path .join (DSS_CAPI_PATH , 'lib/{}' .format (PLATFORM_FOLDER ))
178- ],
179- include_dirs = [
180- os .path .join (DSS_CAPI_PATH , 'include' ),
181- # os.path.join(DSS_CAPI_PATH, 'include/altdss'),
182- ],
183- source_extension = '.c' ,
184- ** extra
185- )
160+ with open ('cffi/dss_capi_custom.h' , 'r' ) as f :
161+ extra_header_dss = f .read ()
186162
187- ffi_builders [version ] = ffi_builder_dss
163+ cffi_header_dss += extra_header_dss
164+ extra_source_dss = ''
165+ with open ('cffi/dss_capi_custom.c' , 'r' ) as f :
166+ extra_source_dss = '#include <altdss/capi/enums.h>\n '
167+ extra_source_dss += '#include <altdss/capi/common.h>\n '
168+ extra_source_dss += '#include <altdss/capi/capi.h>\n '
169+ extra_source_dss += f .read ()
170+
171+ ffi_builder_dss .cdef (cffi_header_dss )
172+
173+ lib_dir = os .path .join (DSS_CAPI_PATH , 'lib/{}' .format (PLATFORM_FOLDER ))
174+ inc_dir = os .path .join (DSS_CAPI_PATH , 'include' )
188175
176+ ffi_builder_dss .set_source (f"_altdss_capi_loader" , extra_source_dss ,
177+ libraries = ['altdss_capi_loader' ],
178+ define_macros = [('HAS_ALTDSS_LOADER_FUNC' , 1 )],
179+ library_dirs = [
180+ lib_dir
181+ ],
182+ include_dirs = [
183+ inc_dir ,
184+ # os.path.join(DSS_CAPI_PATH, 'include/altdss'),
185+ ],
186+ source_extension = '.c' ,
187+ ** extra
188+ )
189189
190190# User-model modules/DLLs
191191# Currently we build a separate DLL for each kind of model,
@@ -225,7 +225,7 @@ def process_header(src, extern_py=False, implement_py=False, prefix='', flags=No
225225 ffi_builder .set_source (f"_dss_{ user_model } _{ variant } " , user_model_src ,
226226 libraries = [],
227227 library_dirs = [],
228- include_dirs = [os . path . join ( DSS_CAPI_PATH , 'include' ) ],
228+ include_dirs = [inc_dir ],
229229 source_extension = '.c' ,
230230 extra_compile_args = variant_flags ,
231231 #extra_link_args=['/DYNAMICBASE:NO', '/NXCOMPAT:NO']
@@ -234,11 +234,6 @@ def process_header(src, extern_py=False, implement_py=False, prefix='', flags=No
234234
235235# Is there a better way to do this? Unfortunately setup(cffi_modules=...)
236236# needs a list of strings and cannot handle objects directly
237- ffi_builder_ = ffi_builders ['altdss_capi' ]
238- ffi_builder_d = ffi_builders ['altdss_capid' ]
239- if BUILD_ODDIE :
240- ffi_builder_odd = ffi_builders ['altdss_oddie_capi' ]
241-
242237ffi_builder_GenUserModel_altdss = ffi_builders ['GenUserModel-AltDSS' ]
243238ffi_builder_GenUserModel_v7 = ffi_builders ['GenUserModel-OpenDSS_v7' ]
244239ffi_builder_GenUserModel_v8v9 = ffi_builders ['GenUserModel-OpenDSS_v8v9' ]
@@ -247,7 +242,20 @@ def process_header(src, extern_py=False, implement_py=False, prefix='', flags=No
247242#ffi_builder_StoreDynaModel = ffi_builders['StoreDynaModel']
248243#ffi_builder_StoreUserModel = ffi_builders['StoreUserModel']
249244#ffi_builder_CapUserControl = ffi_builders['CapUserControl']
250-
245+
246+
247+ _fast_dss_options = dict (
248+ py_limited_api = True ,
249+ include_dirs = [numpy .get_include (), inc_dir ],
250+ libraries = ['altdss_capi_loader' ],
251+ library_dirs = [lib_dir ],
252+ extra_link_args = ["-Wl,-R,$ORIGIN/." ],
253+ # extra_compile_args=['-g', '-O0'],
254+ # extra_link_args=['-g'],
255+ )
256+
257+ fastdss_extension = Extension ('_fastdss' , ["src/_fastdss.c" ], ** _fast_dss_options )
258+
251259if __name__ == "__main__" :
252260 for version , builder in ffi_builders .items ():
253261 print ('-' * 40 )
0 commit comments