LoginSignup
5
3

More than 5 years have passed since last update.

C++でeval() (int以外も使えるようにしてみた)

Last updated at Posted at 2012-03-16
  • 元ネタ : 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

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3