Skip to content

Commit c256ee6

Browse files
chaterpaulADO Sync
andauthored
Sync changes from v25-0-0 (#10)
Co-authored-by: ADO Sync <ado-sync@bentley.com>
1 parent f6c2d6f commit c256ee6

File tree

607 files changed

+120022
-63615
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

607 files changed

+120022
-63615
lines changed

InternalAPI/MSPyCommon.h

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#pragma once
99
#include "ScriptEngineManager.h"
1010

11+
using namespace std;
12+
1113
#define _CRT_SECURE_NO_WARNINGS
1214

1315
#define __EXPAND(x) x
@@ -45,17 +47,128 @@ struct mspydelete {
4547

4648
// Smart pointer declaration
4749
PYBIND11_DECLARE_HOLDER_TYPE(RefCountedBaseT, RefCountedPtr<RefCountedBaseT>, false);
50+
PYBIND11_DECLARE_HOLDER_TYPE(T, TempObjectOwner<T>, false);
4851

4952
// Non-delete smart pointer
5053
#define DEFINE_NODELETE_HOLDER_TYPE(type) using type##Ptr = std::unique_ptr<type, py::nodelete>
5154

55+
namespace std {
56+
template <typename _Ty1, typename _Ty2>
57+
struct tuple_size<Bentley::Bstdcxx::bpair<_Ty1, _Ty2>> : std::integral_constant<size_t, 2> {};
58+
59+
template<class _Ty1,class _Ty2>
60+
struct tuple_element<0, Bentley::Bstdcxx::bpair<_Ty1, _Ty2> >
61+
{ // struct to determine type of element 0 in pair
62+
typedef _Ty1 type;
63+
};
64+
65+
template<class _Ty1, class _Ty2>
66+
struct tuple_element<1, Bentley::Bstdcxx::bpair<_Ty1, _Ty2> >
67+
{ // struct to determine type of element 1 in pair
68+
typedef _Ty2 type;
69+
};
70+
71+
template <typename _Rtype, typename _Ty1, typename _Ty2>
72+
constexpr _Rtype _Pair_get(Bentley::Bstdcxx::bpair<_Ty1, _Ty2>& _Pr, std::integral_constant<size_t, 0>) noexcept {
73+
return _Pr.first;
74+
}
75+
76+
template <typename _Rtype, typename _Ty1, typename _Ty2>
77+
constexpr _Rtype _Pair_get(Bentley::Bstdcxx::bpair<_Ty1, _Ty2>& _Pr, std::integral_constant<size_t, 1>) noexcept {
78+
return _Pr.second;
79+
}
80+
81+
template<size_t _Idx,
82+
class _Ty1,
83+
class _Ty2> inline
84+
constexpr typename tuple_element<_Idx, Bentley::Bstdcxx::bpair<_Ty1, _Ty2> >::type&
85+
get (Bentley::Bstdcxx::bpair<_Ty1, _Ty2>& _Pr) noexcept
86+
{ // get reference to element at _Idx in pair _Pr
87+
typedef typename tuple_element<_Idx, pair<_Ty1, _Ty2> >::type& _Rtype;
88+
return (_Pair_get<_Rtype>(_Pr, integral_constant<size_t, _Idx>()));
89+
};
90+
91+
template<class _Ty1,
92+
class _Ty2> inline
93+
constexpr _Ty1& get(Bentley::Bstdcxx::bpair<_Ty1, _Ty2>& _Pr) noexcept
94+
{ // get reference to element _Ty1 in pair _Pr
95+
return (_STD get<0>(_Pr));
96+
};
97+
98+
template<class _Ty2,
99+
class _Ty1> inline
100+
constexpr _Ty2& get(Bentley::Bstdcxx::bpair<_Ty1, _Ty2>& _Pr) noexcept
101+
{ // get reference to element _Ty2 in pair _Pr
102+
return (_STD get<1>(_Pr));
103+
};
104+
105+
template<size_t _Idx,
106+
class _Ty1,
107+
class _Ty2> inline
108+
constexpr typename tuple_element<_Idx, Bentley::Bstdcxx::bpair<_Ty1, _Ty2> >::type&&
109+
get (Bentley::Bstdcxx::bpair<_Ty1, _Ty2>&& _Pr) noexcept
110+
{ // get rvalue reference to element at _Idx in pair _Pr
111+
typedef typename tuple_element<_Idx, pair<_Ty1, _Ty2> >::type&& _RRtype;
112+
return (_STD forward<_RRtype>(_STD get<_Idx>(_Pr)));
113+
};
114+
115+
template<class _Ty1,
116+
class _Ty2> inline
117+
constexpr _Ty1&& get(Bentley::Bstdcxx::bpair<_Ty1, _Ty2>&& _Pr) noexcept
118+
{ // get rvalue reference to element _Ty1 in pair _Pr
119+
return (_STD get<0>(_STD move(_Pr)));
120+
};
121+
122+
template<class _Ty2,
123+
class _Ty1> inline
124+
constexpr _Ty2&& get(Bentley::Bstdcxx::bpair<_Ty1, _Ty2>&& _Pr) noexcept
125+
{ // get rvalue reference to element _Ty2 in pair _Pr
126+
return (_STD get<1>(_STD move(_Pr)));
127+
};
128+
129+
template<size_t _Idx,
130+
class _Ty1,
131+
class _Ty2> inline
132+
constexpr const typename tuple_element<_Idx, Bentley::Bstdcxx::bpair<_Ty1, _Ty2> >::type&
133+
get (const Bentley::Bstdcxx::bpair<_Ty1, _Ty2>& _Pr) noexcept
134+
{ // get const reference to element at _Idx in pair _Pr
135+
typedef const typename tuple_element<_Idx, pair<_Ty1, _Ty2> >::type&
136+
_Ctype;
137+
return (_Pair_get<_Ctype>(_Pr, integral_constant<size_t, _Idx>()));
138+
};
139+
140+
template<class _Ty1,
141+
class _Ty2> inline
142+
constexpr const _Ty1& get(const Bentley::Bstdcxx::bpair<_Ty1, _Ty2>& _Pr) noexcept
143+
{ // get const reference to element _Ty1 in pair _Pr
144+
return (_STD get<0>(_Pr));
145+
}
146+
147+
template<class _Ty2,
148+
class _Ty1> inline
149+
constexpr const _Ty2& get(const Bentley::Bstdcxx::bpair<_Ty1, _Ty2>& _Pr) noexcept
150+
{ // get const reference to element _Ty2 in pair _Pr
151+
return (_STD get<1>(_Pr));
152+
}
153+
}
154+
52155
namespace PYBIND11_NAMESPACE {
53156
namespace detail {
54157
template <typename T>
55158
struct type_caster<boost::optional<T>> : optional_caster<boost::optional<T>> {};
159+
160+
template <typename T1, typename T2>
161+
class type_caster<Bentley::Bstdcxx::bpair<T1, T2>> : public tuple_caster<Bentley::Bstdcxx::bpair, T1, T2> {};
162+
163+
template <typename Key, typename Compare, typename Alloc>
164+
struct type_caster<Bentley::bset<Key, Compare, 32, Alloc>>
165+
: set_caster<Bentley::bset<Key, Compare, 32, Alloc>, Key> {};
56166
}
57167
}
58168

169+
170+
171+
59172
// PYBIND11_OVERRIDE with exception capture and has return value.
60173
#define PYBIND11_OVERRIDE_EXR(ret_type, cname, fn, error, ...) \
61174
try \
@@ -215,3 +328,72 @@ py::class_<bvector<ValueType>, holder_type> bind_PointerVector(py::handle scope,
215328

216329
return cls;
217330
}
331+
332+
// Convert Python list to an existing C++ array
333+
template <typename arrayType, typename itemType>
334+
void ConvertPyListToCppArray(py::list const& pyList, arrayType& cppArray)
335+
{
336+
cppArray.clear();
337+
for (auto item : pyList)
338+
{
339+
if (!py::isinstance<itemType>(item))
340+
{
341+
throw std::invalid_argument("All items in the list must be of the correct item type");
342+
}
343+
auto cppItem = item.cast<itemType>();
344+
cppArray.push_back(cppItem);
345+
}
346+
}
347+
348+
// Convert Python list to a new C++ array
349+
template <typename arrayType, typename itemType>
350+
arrayType ConvertPyListToCppArray(py::list const& pyList)
351+
{
352+
arrayType cppArray;
353+
for (auto item : pyList)
354+
{
355+
if (!py::isinstance<itemType>(item))
356+
{
357+
throw std::invalid_argument("All items in the list must be of the correct item type");
358+
}
359+
auto cppItem = item.cast<itemType>();
360+
cppArray.push_back(cppItem);
361+
}
362+
return cppArray;
363+
}
364+
365+
// Convert C++ array to an existing Python list
366+
template <typename arrayType, typename itemType>
367+
void ConvertCppArrayToPyList(py::list& pyList, arrayType const& cppArray)
368+
{
369+
pyList.attr("clear")();
370+
for (const itemType& item : cppArray)
371+
{
372+
pyList.append(py::cast(item));
373+
}
374+
}
375+
376+
// Convert C++ array to a new Python list
377+
template <typename arrayType, typename itemType>
378+
py::list ConvertCppArrayToPyList(arrayType const& cppArray)
379+
{
380+
py::list pyList;
381+
for (const itemType& item : cppArray)
382+
{
383+
pyList.append(py::cast(item));
384+
}
385+
return pyList;
386+
}
387+
388+
// Macros
389+
#define CONVERT_PYLIST_TO_CPPARRAY(pyList, cppArray, cppArrayType, cppItemType) \
390+
ConvertPyListToCppArray<cppArrayType, cppItemType>(pyList, cppArray);
391+
392+
#define CONVERT_PYLIST_TO_NEW_CPPARRAY(pyList, cppArray, cppArrayType, cppItemType) \
393+
cppArrayType cppArray = ConvertPyListToCppArray<cppArrayType, cppItemType>(pyList);
394+
395+
#define CONVERT_CPPARRAY_TO_PYLIST(pyList, cppArray, cppArrayType, cppItemType) \
396+
ConvertCppArrayToPyList<cppArrayType, cppItemType>(pyList, cppArray);
397+
398+
#define CONVERT_CPPARRAY_TO_NEW_PYLIST(pyList, cppArray, cppArrayType, cppItemType) \
399+
py::list pyList = ConvertCppArrayToPyList<cppArrayType, cppItemType>(cppArray);

InternalAPI/OpqueTypes_Bentley.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ DEFINE_BVECTOR_TYPE(Utf8String, Utf8StringArray);
3030
// Commonly used bmap
3131
DEFINE_BMAP_TYPE(WString, WString, WStringWStringMap);
3232
DEFINE_BMAP_TYPE(WString, WCharCP, WStringWCharMap);
33+
DEFINE_BMAP_TYPE(int, int, IntIntMap);

InternalAPI/OpqueTypes_Geom.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ DEFINE_BVECTOR_TYPE(DPoint3dArray, DPoint3dVecArray);
2424
DEFINE_BVECTOR_TYPE(DPoint3dVecArray, DPoint3dVecVecArray);
2525
DEFINE_BVECTOR_TYPE(DVec3dArray, DVec3dVecArray);
2626
DEFINE_BVECTOR_TYPE(ICurvePrimitivePtr, ICurvePrimitiveArray);
27+
DEFINE_BVECTOR_TYPE(CurvePrimitivePtrPair, CurvePrimitivePtrPairArray);
2728
DEFINE_BVECTOR_TYPE(DSegment1d, DSegment1dArray);
2829
DEFINE_BVECTOR_TYPE(DSegment3d, DSegment3dArray);
2930
DEFINE_BVECTOR_TYPE(CurveLocationDetail, CurveLocationDetailArray);

MSPythonCore.mke

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#--------------------------------------------------------------------------------------
88
appName = MSPythonCore
99

10+
1011
%if defined (BSIBUILD)
1112
MSPythonSrc = $(SrcRoot)MSPython/
1213
%else
@@ -41,7 +42,7 @@ MultiCompileDepends = $(_MakeFileSpec)
4142
PchCompiland = $(baseDir)MSPythonPCH.cpp
4243
PchOutputDir = $(o)
4344
PchArgumentsDepends = $(MultiCompileDepends)
44-
PchExtraOptions + -Zm170 -wd4456 -wd4457 -wd4459 -wd4311 -wd4312 -wd4302 -wd4471
45+
PchExtraOptions + -Zm170 -wd4456 -wd4457 -wd4459 -wd4311 -wd4312 -wd4302 -wd4471 -wd4653 -wd4652 -wd4651
4546

4647
%include $(MSPythonSrc)/build/publicSDK/PreCompileHeader.mki
4748

MSPythonCore/ScriptEngineManager/source/MSPythonEngine.cpp

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -733,12 +733,14 @@ ScriptValuePtr PythonScriptEngine::eval(WCharCP expr, ScriptContext* global, Scr
733733
ScriptEngineManager::Get().ClearException();
734734
try
735735
{
736+
mdlErrno = 0;
736737
py::object obj = py::eval(py::cast(expr), globalDict, py::len(localDict) > 0 ? localDict : py::object ());
737738
outVal = new PythonScriptValue(obj);
738739
}
739740
catch (py::error_already_set& err)
740741
{
741742
ScriptEngineManager::Get().InjectException(err);
743+
mdlErrno = MDLERR_PYTHONEXECUTIONERROR;
742744
}
743745

744746
m_engineProcessing = false;
@@ -783,16 +785,56 @@ void PythonScriptEngine::exec(WCharCP stms, WCharCP funcName, ScriptContext* glo
783785
m_engineProcessing = true;
784786
try
785787
{
788+
mdlErrno = 0;
786789
py::exec(py::cast(stms), globalDict, py::len(localDict) > 0 ? localDict : py::object ());
787790
}
788791
catch (py::error_already_set& err)
789792
{
790793
ScriptEngineManager::Get().InjectException(err);
794+
mdlErrno = MDLERR_PYTHONEXECUTIONERROR;
791795
}
792796
m_engineProcessing = false;
793797

794798
}
795799

800+
801+
/*---------------------------------------------------------------------------------**//***
802+
@bsimethod 3/2025
803+
+---------------+---------------+---------------+---------------+---------------+------*/
804+
static bool isPydLoadingFailed(const std::string& nameModule)
805+
{
806+
auto& internals = py::detail::get_internals();
807+
auto& registered_types_cpp = internals.registered_types_cpp;
808+
809+
for (const auto& item : registered_types_cpp)
810+
{
811+
std::string name = item.second->type->tp_name;
812+
if (name.find(nameModule) != std::string::npos)
813+
{
814+
py::module_ sys = py::module_::import("sys");
815+
if (sys.attr("modules").contains(nameModule))
816+
return false; //loaded successfully
817+
else
818+
return true; //failed to load
819+
}
820+
}
821+
822+
return false; // not found
823+
}
824+
825+
/*---------------------------------------------------------------------------------**//***
826+
@bsimethod 3/2025
827+
+---------------+---------------+---------------+---------------+---------------+------*/
828+
static bool allPydsLoadedSuc()
829+
{
830+
if (isPydLoadingFailed("MSPyBentley") || isPydLoadingFailed("MSPyBentleyGeom") ||
831+
isPydLoadingFailed("MSPyECObjects") || isPydLoadingFailed("MSPyDgnPlatform") ||
832+
isPydLoadingFailed("MSPyDgnView") || isPydLoadingFailed("MSPyMstnPlatform"))
833+
return false;
834+
835+
return true;
836+
}
837+
796838
/*---------------------------------------------------------------------------------**//***
797839
@bsimethod 12/2024
798840
+---------------+---------------+---------------+---------------+---------------+------*/
@@ -808,6 +850,10 @@ static void getCachedTypes(std::unordered_map<std::type_index, std::string>& bef
808850
+---------------+---------------+---------------+---------------+---------------+------*/
809851
static void removeCachedtypes(const std::unordered_map<std::type_index, std::string>& before_type_cache)
810852
{
853+
if (allPydsLoadedSuc())
854+
return;
855+
856+
//TODO: call py::finalize_interpreter()&py::initialize_interpreter() to restart the python interpreter
811857
auto& internals = py::detail::get_internals();
812858
for (auto it = internals.registered_types_cpp.begin(); it != internals.registered_types_cpp.end();)
813859
{
@@ -849,7 +895,7 @@ void PythonScriptEngine::eval_file(WCharCP scriptFile, WCharCP funcName, ScriptC
849895
auto pyLocalDict = dynamic_cast<PythonScriptContext*>(localCtx.get());
850896
if (nullptr != pyLocalDict)
851897
localDict = pyLocalDict->m_dict;
852-
898+
853899
m_engineProcessing = true;
854900

855901
// The cache of types registered by pybind11 before running the script
@@ -861,18 +907,21 @@ void PythonScriptEngine::eval_file(WCharCP scriptFile, WCharCP funcName, ScriptC
861907
{
862908
try
863909
{
864-
// Run file, Python returns errors if the local dictionary is empty
910+
mdlErrno = 0;
911+
// Python returns errors if the local dictionary is empty
865912
py::eval_file(py::cast(scriptFile), globalDict, py::len(localDict) > 0 ? localDict : py::object ());
866913
}
867914
catch (py::error_already_set& e)
868915
{
869-
removeCachedtypes(before_type_cache);
870916
ScriptEngineManager::Get().InjectError( e.what ());
917+
mdlErrno = MDLERR_PYTHONEXECUTIONERROR;
918+
removeCachedtypes(before_type_cache);
871919
}
872920
catch (std::exception& err)
873921
{
874-
removeCachedtypes(before_type_cache);
875922
ScriptEngineManager::Get().InjectException(err);
923+
mdlErrno = MDLERR_PYTHONEXECUTIONERROR;
924+
removeCachedtypes(before_type_cache);
876925
}
877926
}
878927
else // User want to run a function inside given module
@@ -895,14 +944,15 @@ void PythonScriptEngine::eval_file(WCharCP scriptFile, WCharCP funcName, ScriptC
895944
WString function(funcName);
896945

897946
function.append (L" ()");
898-
947+
mdlErrno = 0;
899948
py::exec(py::cast(function.c_str ()) ,globalDict, localDict);
900949

901950
}
902951
catch (std::exception& err)
903952
{
904-
removeCachedtypes(before_type_cache);
905953
ScriptEngineManager::Get().InjectException(err);
954+
mdlErrno = MDLERR_PYTHONEXECUTIONERROR;
955+
removeCachedtypes(before_type_cache);
906956
}
907957
}
908958
m_engineProcessing = false;

0 commit comments

Comments
 (0)