- 元ネタ : http://d.hatena.ne.jp/kura-replace/20110926/1317050052
- 元ネタのだとintしか返せなかったのでいじってみた
- 戻り値を検出する方法が思い浮かばなかったので現状だと eval() って形になってる
- DLL使うからWindowsじゃないと動かない
- MinGW4.5.2、msvc10.0(VC++2010)で動作ほんのり確認
- MinGWならBoostも使えた(lexical_castしか試してないけど)
- 使い方は元ネタ参照 テンプレート引数は第二引数に渡す「得たい戻り値の型」を指定する
eval.hpp
#ifndef __ICL_EVAL_HPP_INCLUDED
#define __ICL_EVAL_HPP_INCLUDED
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <windows.h>
#ifndef __ICL_EVAL_TEMP_NAME__
#define __ICL_EVAL_TEMP_NAME__ "______________________________________________"
#endif
namespace ICL{
template<typename RetT>RetT eval(const std::string& Source,const std::string& ReturnStatement){
const std::string eval_temp_filename = __ICL_EVAL_TEMP_NAME__;
std::ofstream o((eval_temp_filename+".cpp").c_str());
o<<Source<<"\nextern \"C\" "
#ifdef _MSC_VER
"__declspec(dllexport) "
#endif
"decltype("<<ReturnStatement<<") "
<<eval_temp_filename<<"(){return ("<<ReturnStatement<<");}"<<std::endl;
o.close();
#ifdef _MSC_VER
std::system(('"'+std::string(getenv("VS100COMNTOOLS"))+"..\\..\\VC\\bin\\vcvars32.bat\"").c_str());
std::system(("cl /MD /LD "+eval_temp_filename+".cpp").c_str());
std::remove((eval_temp_filename+".lib").c_str());
std::remove((eval_temp_filename+".obj").c_str());
std::remove((eval_temp_filename+".exp").c_str());
#endif
#ifdef __GNUC__
std::system(("g++ -std=c++0x -static -shared -o "+eval_temp_filename+".dll "+eval_temp_filename+".cpp").c_str());
#endif
std::remove((eval_temp_filename+".cpp").c_str());
struct __{
const std::string eval_temp_filename;
HMODULE Dll;
__() : eval_temp_filename(__ICL_EVAL_TEMP_NAME__),Dll(LoadLibrary((eval_temp_filename+".dll").c_str())){if(!Dll)throw GetLastError();}
~__(){FreeLibrary(Dll);std::remove((eval_temp_filename+".dll").c_str());}
RetT operator()(){
typedef RetT (*Func)();
Func f=reinterpret_cast<Func>(GetProcAddress(Dll,eval_temp_filename.c_str()));
if(!f)throw GetLastError();
return f();
}
}f;
return f();
}
template<typename RetT>RetT eval(const std::string& ReturnStatement){return eval<RetT>("",ReturnStatement);}
}//End : namespace ICL
#endif //__ICL_EVAL_HPP_INCLUDED