Обновлено 24.2.2017
Раньше я анализировал поддержку использования # define и, как это рекомендуется в некоторых веб-статьях - я попал в определения, которые на Visual C ++ не работали одинаково по сравнению с используемым определением в gcc (например, в интернете это довольно часто называют «прогулкой по MSVC»). Кроме того, вы не сможете легко понять, что происходит за механизмом разработки / макрорасширения - довольно сложно отладить каждое расширение макросов.
Существует несколько способов обойти сложности определения расширения, одним из подходов является включение флага компилятора «/ P» (только для предварительного процесса в файл) - после этого вы можете сравнить, как открывается ваш определение вверх. (Раньше я также активно использовал stringfy operator (#))
Я собрал все полезные определения из нескольких форумов, применил их и закомментировал, что происходит за машиной, вы можете найти весь заголовочный файл в здесь:
https://sourceforge.net/p/testcppreflect/code/HEAD/tree/MacroHelpers.h
Я думал, что это скорее тривиально использовать эти макросы, чтобы включить отражение C ++, но для этого требуется немного больше волшебства.
Я вспомнил рабочий пример кода и поместил его в качестве проекта sourceforge, можно скачать здесь:
https://sourceforge.net/p/testcppreflect/code/HEAD/tree/
Демо-код выглядит следующим образом:
#include "CppReflect.h"
using namespace std;
class Person
{
public:
REFLECTABLE( Person,
(CString) name,
(int) age
)
};
class People
{
public:
REFLECTABLE( People,
(CString) groupName,
(vector) people
)
};
void main(void)
{
People ppl;
ppl.groupName = "Group1";
Person p;
p.name = L"Roger";
p.age = 37;
ppl.people.push_back(p);
p.name = L"Alice";
p.age = 27;
ppl.people.push_back( p );
p.name = L"Cindy";
p.age = 17;
ppl.people.push_back( p );
CStringA xml = ToXML( &ppl );
CStringW errors;
People ppl2;
FromXml( &ppl2, xml, errors );
CStringA xml2 = ToXML( &ppl2 );
printf( xml2 );
}
REFLECTABLE define использует имя класса + имя поля с offsetof - для определения того, в каком месте в памяти находится определенное поле. Я попытался подобрать терминологию .NET, насколько это возможно, но C ++ и C # отличаются друг от друга, поэтому это не от 1 до 1. Модель отражения всего C ++ находится в классах TypeInfo и FieldInfo для обеспечения времени, возможно расширить поддержку и метода , но я решил сохранить все просто.
Я использовал парсинг pugi xml для извлечения демонстрационного кода в xml и восстановления его обратно из xml.
Таким образом, вывод, созданный демо-код выглядит следующим образом:
Также возможно включить любую поддержку 3-го партийного класса / структуры через класс TypeTraits и спецификацию частичного шаблона - определить свой собственный класс TypeTraitsT
, в аналогичном способ CString
или int
- см. пример кода в
https://sourceforge.net/p/testcppreflect/code/HEAD/tree/TypeTraits.h#l65
template <>
class TypeTraitsT : public TypeTraits
{
public:
virtual CStringW ToString( void* pField )
{
CString* s = (CString*)pField;
return *s;
}
virtual void FromString( void* pField, const wchar_t* value )
{
CString* s = (CString*)pField;
*s = value;
}
};
template <>
class TypeTraitsT : public TypeTraits
{
public:
virtual CStringW ToString( void* pField )
{
int* p = (int*) pField;
return std::to_string(*p).c_str();
}
virtual void FromString( void* pField, const wchar_t* value )
{
int* p = (int*)pField;
*p = _wtoi(value);
}
};
Я полагаю, что только недостатком моей собственной реализации является использование __if_exists
- это может быть специфическое расширение компилятора Microsoft. Если кто-то знает, как ходить вокруг, дайте мне знать.
Все, кажется, хотят сказать Вам, что необходимо делать вместо того, чтобы просто ответить на вопрос.
проблема состоит в том, что Вы выполняете модуль как '__ основной __' путем передачи mod1.py как аргумента интерпретатору.
От PEP 328:
Относительный импорт использует модуль __ имя __ атрибут, чтобы решить что положение модуля в иерархии пакета. Если имя модуля не содержит информации о пакете (например, это установлено на '__ основной __'), тогда, относительный импорт разрешен, как будто модуль был высокоуровневым модулем, независимо от того, где модуль на самом деле расположен в файловой системе.
В Python 2.6, они добавляют способность сослаться на модули относительно основного модуля. PEP 366 описывает изменение.
Обновление : По словам Nick Coghlan, рекомендуемая альтернатива должна выполнить модуль в пакете с помощью переключателя-m.
main.py
setup.py
app/ ->
__init__.py
package_a/ ->
__init__.py
module_a.py
package_b/ ->
__init__.py
module_b.py
python main.py
. main.py
делает: import app.package_a.module_a
module_a.py
делает import app.package_b.module_b
, Кроме того, 2, или 3 мог использовать: from app.package_a import module_a
, Который будет работать, пока Вы имеете app
в Вашем PYTHONPATH. main.py
мог быть где угодно тогда.
, Таким образом, Вы пишете setup.py
для копирования (устанавливают) целый пакет приложения и подпакеты к папкам Python целевой системы, и main.py
для предназначения для папок сценария системы.
def import_path(fullpath):
"""
Import a file with full path specification. Allows one to
import from anywhere, something __import__ does not do.
"""
path, filename = os.path.split(fullpath)
filename, ext = os.path.splitext(filename)
sys.path.append(path)
module = __import__(filename)
reload(module) # Might be out of date
del sys.path[-1]
return module
Я использую этот фрагмент для импорта модулей из путей, надеюсь, что это поможет