C++반사 실현-RTTR 라 이브 러 리 사용

5102 단어 경험 공유
C\#또는 자바 의 동 화 를 사용 한 적 이 있 으 므 로 이러한 언어 가 제공 하 는 반사 메커니즘 에 대해 알 아야 한다.반사 란 내 가 보기 에는 하나의 이름(문자열 형식)만 알 고 있 는 상황 에서 구체 적 인 인 인 스 턴 스 를 자동 으로 만 들 고 이 유형 이 가지 고 있 는 속성,방법 등 정 보 를 매 거 할 수 있 는 것 이다.반사 적 으로 쓴 코드 를 사용 하면 매우 정교 하고 간결 하 게 할 수 있다.
우리 가 최근 에 개발 한 제품 은 C++언어 를 사용 하기 때문에 이런 언어 는 반사 메커니즘 을 내장 하지 않 았 다.그래서 인터넷 에서 조사 연 구 를 실시 한 결과 C++반사 지원 을 제공 하 는 좋 은 라 이브 러 리,예 를 들 어 CPP-Reflection,Vlpp,ponder 등 을 발견 했다.저희 제품 은 VS 2013 으로 개 발 된 것 으로 C++11 에 대한 지원 이 완선 되 지 않 습 니 다.이런 라 이브 러 리 는 보통 VS 2015 를 사용 해 야 컴 파일 할 수 있 습 니 다.결국 저 는 RTTR 라 는 오픈 소스 라 이브 러 리(Github 주소:RTTR 전송 문)를 선 택 했 습 니 다.관심 있 는 동 화 는 스스로 컴 파일 할 수 있 습 니 다.여 기 는 VS 2013 컴 파일 된 x64 와 x86 프 리 컴 파일 백 을 제공 합 니 다.
다음은 이 라 이브 러 리 의 사용법 을 간단 한 예제 로 보 여 줍 니 다.
Person.h
#include 

namespace World
{
	class Person
	{
	public:
		Person();
		~Person();

		void set_name(const std::string& name);
		const std::string& get_name() const;

		void set_age(int age);
		int get_age();

		virtual void show();

		void growupTo(int age=20);

	private:
		std::string m_name;
		int m_age;

		RTTR_ENABLE()
	};
}
Person.cpp
#include "Person.h"
#include 
#include 

namespace World
{
	RTTR_REGISTRATION
	{
		rttr::registration::class_("World::Person")
			.constructor<>()
			(
				rttr::policy::ctor::as_std_shared_ptr
			)
			.property("name", &Person::get_name, &Person::set_name)
			.property("age", &Person::get_age, &Person::set_age)
			.method("show", &Person::show)
			.method("growupTo", &Person::growupTo)
			(
				rttr::default_arguments(18),
				rttr::parameter_names("age")
			)
			;
	}

	Person::Person()
		:m_age(0)
	{
	}


	Person::~Person()
	{
	}

	void Person::set_name(const std::string& name)
	{
		m_name = name;
	}

	const std::string& Person::get_name() const
	{
		return m_name;
	}

	void Person::set_age(int age)
	{
		m_age = age;
	}

	int Person::get_age()
	{
		return m_age;
	}

	void Person::show()
	{
		std::cout << "     : " << m_name << ",    " << m_age << " " << std::endl;
	}

	void Person::growupTo(int age/* =20 */)
	{
		m_age = age;
		std::cout << m_name << "   : " << m_age << " " << std::endl;
	}
}

main.cpp
#include 
#include 

int _tmain(int argc, _TCHAR* argv[])
{
	rttr::type t = rttr::type::get_by_name("World::Person");

	rttr::variant var = t.create();

	rttr::property prop = t.get_property("name");

	prop.set_value(var, std::string("  "));

	prop = t.get_property("age");

	prop.set_value(var, 18);

	rttr::method meth = t.get_method("show");

	meth.invoke(var);

	std::cout << "  : " << std::endl;

	for (auto& prop : t.get_properties())
	{
		std::cout << "   : " << prop.get_name() << ",     : " << prop.get_type().get_name() << std::endl;
	}

	std::cout << "  : " << std::endl;

	for (auto& meth : t.get_methods())
	{
		std::cout << "    : " << meth.get_name() << ",     : " << meth.get_signature() << std::endl;
		for (auto& info : meth.get_parameter_infos())
		{
			std::cout << "      : " << info.get_index() << ",    " << info.get_name() << std::endl;
		}
	}

	getchar();

	return 0;
}

main.cpp 에 Person.h 를 인용 하지 않 았 지만 Person 의 인 스 턴 스 를 만 들 었 음 을 알 수 있 습 니 다.
때로는 RTTR 의 variant 를 구체 적 인 클래스 로 바 꿔 야 할 수도 있 습 니 다.Person.cpp 에 있 는 RTTR 을 볼 수 있 습 니 다.REGISTRATION 블록 에서 Person 클래스 의 구조 함수 에 rttr::policy::ctor::as 를 사 용 했 습 니 다.std_shared_ptr 의 설명,선택 할 수 있 는 것 은 rttr::policy::ctor::asobject 와 rttr::policy::ctor::asraw_ptr。이 세 가지 상황 에서 코드 의 작성 방식 이 모두 다 르 기 때문에 상세 한 것 은 RTTR 의 공식 튜 토리 얼 을 참조 할 수 있다.다음은 여러 가지 상황 에서 의 변환 기법 을 보 여 줍 니 다.
4.567913.물론 이 때 는 Person.h 를 포함해 야 합 니 다.
주:프로젝트 컴 파일 에 실패 하면 error LNK 2001:unsolved external symbol"public:static struct rttr::detail:asobject const rttr::policy::ctor::as_object" (?as_object@ctor@policy@rttr@@2U0detail@3@B)의 오류 입 니 다.사전 컴 파일 매크로 를 추가 해 야 합 니 다:RTTRDLL
나 는 분할 선
실제 사용 과정 에서 주의해 야 할 문제 들 이 또 발견 되 었 다.우리 의 프로젝트 구 조 는 먼저 정적 링크 라 이브 러 리(lib)를 컴 파일 하고 최종 exe 에서 이 파일 들 을 연결 하 는 것 입 니 다.두 가지 문제 가 있 습 니 다.
1.이러한 lib 사이 에 도 인용 관계 가 존재 합 니 다.rrtr 가 lib 1 에서 사용 된다 고 가정 하면 rttr 2 는 rtt 1 을 인용 합 니 다.그러면 exe 에서 lib 1 과 lib 2 를 연결 하면 lib 2 가 RTTR 을 정의 하지 않 으 면DLL 프 리 컴 파일 매크로 는 이상 한 링크 오 류 를 보고 하기 때문에 lib 2 도 프로젝트 설정 에 RTTR 을 추가 해 야 합 니 다.DLL。
2.lib 1 에 있 는 class 1 이 rttr 를 사용 한 다음 exe 링크 lib 1 을 사용 했다 고 가정 합 니 다.exe 에 있 는 모든 컴 파일 에 참여 하 는 cpp 에서 class 1 류(임시 변수,전역 변수 또는 new 포인터 정의 포함)를 사용 하지 않 았 다 면 클래스 이름 에 따라 동적 으로 클래스 를 만 드 는 데 실 패 했 습 니 다(rttr:type:getby_name("World::Person"))。제 해결 방법 은 컴 파일 에 참여 하 는 cpp 파일 을 마음대로 찾 는 것 입 니 다.파일 의 시작 부분 에 전체적인 class 1 을 정의 하면 됩 니 다.

좋은 웹페이지 즐겨찾기