让C++动态执行某个文件中的部分C++代码,实现动态代码程序
我在做一个ISAPI时,遇到了这样的问题.
想把C++程序,先写到每个CPP文件中,然后由一个C++写的ISAPI根据不同的外部参数,调用对应的CPP文件,并把CPP文件的代码执行.
在网上查了一些关于C++的EVAL的文章,都是做简单的数学运算或者正则,但我的CPP中包含了复杂的C++代码,不知道如何解决.
还请各位高人指点.
[解决办法]
C++的代码都是编译成可执行文件,然后执行的。你的程序需要先编译成可执行程序,然后执行的时候动态选择代码,再进行编译,生成可执行
文件,然后执行,相当于程序能够自动的判断源代码然后自己编译运行,很有难度啊...
[解决办法]
1.用脚本语言,COM中有支持脚本的...
2.自己写解释器这个比较恼火的说
These files contain all of the code listings in
The Art of C++
The source code is organized into files by chapter.
Within each chapter file, the listings are stored
in the same order as they appear in the book.
Simply edit the appropriate file to extract the
listing in which you are interested.
- C/C++ code
#include <iostream> #include <cstring> #include <cstdlib> #include <cctype> #include "mccommon.h" using namespace std; // Keyword lookup table. // Keywords must be entered lowercase. struct commands { char command[20]; token_ireps tok; } com_table[] = { "if", IF, "else", ELSE, "for", FOR, "do", DO, "while", WHILE, "char", CHAR, "int", INT, "return", RETURN, "switch", SWITCH, "break", BREAK, "case", CASE, "cout", COUT, "cin", CIN, "", END // mark end of table }; // This structure links a library function name // with a pointer to that function. struct intern_func_type { char *f_name; // function name int (*p)(); // pointer to the function } intern_func[] = { "getchar", call_getchar, "putchar", call_putchar, "abs", call_abs, "rand", call_rand, "", 0 // null terminate the list }; // Entry point into parser. void eval_exp(int &value) { get_token(); if(!*token) { throw InterpExc(NO_EXP); } if(*token == ';') { value = 0; // empty expression return; } eval_exp0(value); putback(); // return last token read to input stream }
[解决办法]
我个人觉得,要实现一个这样的程序,必须要在内部实现一个编译器才行!因为这个程序release出去以后,不能保证用户的机器上一定有编
译器,所以必须自身携带编译器。而编译器可以是第一次编译的时候生成的可执行文件里面就附带了。然后release出去以后,在所有的机器
上都能正常的check源码文件,并且和自己的代码揉合,形成一套新的代码,然后调用自身的编译器来进行第二次编译,这个程序就是最终结
果了...
以上只是一个个人考虑的流程,仅供参考!
[解决办法]
The Art of C++
搜索一下,里面最后一章讲了一个简单的C++解释器的实现
[解决办法]
- C/C++ code
//MSDN上内嵌vbs的例子(部分代码)
//建议使用这种方法
//写解释器难度相对较高,成本也大
// Your IActiveScriptSite implementation...
class MyActiveScriptSite : public IActiveScriptSite {
private:
ULONG m_dwRef; // Reference count
public:
IUnknown *m_pUnkScriptObject; // Pointer to your object that is exposed
// to the script engine in GetItemInfo().
MyActiveScriptSite::MyActiveScriptSite() {m_dwRef = 1;}
MyActiveScriptSite::~MyActiveScriptSite() {}
// IUnknown methods...
virtual HRESULT _stdcall QueryInterface(REFIID riid, void **ppvObject) {
*ppvObject = NULL;
return E_NOTIMPL;
}
virtual ULONG _stdcall AddRef(void) {
return ++m_dwRef;
}
virtual ULONG _stdcall Release(void) {
if(--m_dwRef == 0) return 0;
return m_dwRef;
}
// IActiveScriptSite methods...
virtual HRESULT _stdcall GetLCID(LCID *plcid) {
return S_OK;
}
virtual HRESULT _stdcall GetItemInfo(LPCOLESTR pstrName,
DWORD dwReturnMask, IUnknown **ppunkItem, ITypeInfo **ppti) {
// Is it expecting an ITypeInfo?
if(ppti) {
// Default to NULL.
*ppti = NULL;
// Return if asking about ITypeInfo...
if(dwReturnMask & SCRIPTINFO_ITYPEINFO)
return TYPE_E_ELEMENTNOTFOUND;
}
// Is the engine passing an IUnknown buffer?
if(ppunkItem) {
// Default to NULL.
*ppunkItem = NULL;
// Is Script Engine looking for an IUnknown for our object?
if(dwReturnMask & SCRIPTINFO_IUNKNOWN) {
// Check for our object name...
if (!_wcsicmp(L"MyObject", pstrName)) {
// Provide our object.
*ppunkItem = m_pUnkScriptObject;
// Addref our object...
m_pUnkScriptObject->AddRef();
}
}
}
return S_OK;
}
virtual HRESULT __stdcall GetDocVersionString(BSTR *pbstrVersion) {
return S_OK;
}
virtual HRESULT __stdcall OnScriptTerminate(const VARIANT *pvarResult,
const EXCEPINFO *pexcepInfo) {
return S_OK;
}
virtual HRESULT __stdcall OnStateChange(SCRIPTSTATE ssScriptState) {
return S_OK;
}
virtual HRESULT __stdcall OnScriptError(
IActiveScriptError *pscriptError) {
static BSTR pwcErrorText;
pscriptError->GetSourceLineText(&pwcErrorText);
AfxMessageBox(
CString("IActiveScriptSite::OnScriptError()\n") +
CString("Line: ") +
CString(pwcErrorText),
MB_SETFOREGROUND);
::SysFreeString(pwcErrorText);
return S_OK;
}
virtual HRESULT __stdcall OnEnterScript(void) {
return S_OK;
}
virtual HRESULT __stdcall OnLeaveScript(void) {
return S_OK;
}
};
// Global instance of our IActiveScriptSite implementation.
MyActiveScriptSite g_iActiveScriptSite;
// Script Engine CLSIDs...
#include <initguid.h>
DEFINE_GUID(CLSID_VBScript, 0xb54f3741, 0x5b07, 0x11cf, 0xa4, 0xb0, 0x0,
0xaa, 0x0, 0x4a, 0x55, 0xe8);
DEFINE_GUID(CLSID_JScript, 0xf414c260, 0x6ac0, 0x11cf, 0xb6, 0xd1, 0x00,
0xaa, 0x00, 0xbb, 0xbb, 0x58);
// Ole-initialization class.
class OleInitClass {
public:
OleInitClass() {
OleInitialize(NULL);
}
~OleInitClass() {
OleUninitialize();
}
};
// This global class calls OleInitialize() at
// application startup, and calls OleUninitialize()
// at application exit...
OleInitClass g_OleInitClass;
void HRVERIFY(HRESULT hr, char * msg)
{
if(FAILED(hr)) {
CString str;
str.Format("Error: 0x%08lx (%s)", hr, msg);
AfxMessageBox(str, 0x10000);
_exit(0);
}
}
void CDlgTstDlg::OnBnClickedButton1()
{
// Initialize our IActiveScriptSite implementation with your
// script object's IUnknown interface...
g_iActiveScriptSite.m_pUnkScriptObject =
m_myScriptObject.GetInterface(&IID_IUnknown);
// Start inproc script engine, VBSCRIPT.DLL
HRVERIFY(CoCreateInstance(CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER,
IID_IActiveScript, (void **)&m_iActiveScript),
"CoCreateInstance() for CLSID_VBScript");
// Get engine's IActiveScriptParse interface.
HRVERIFY(m_iActiveScript->QueryInterface(IID_IActiveScriptParse,
(void **)&m_iActiveScriptParse),
"QueryInterface() for IID_IActiveScriptParse");
// Give engine our IActiveScriptSite interface...
HRVERIFY(m_iActiveScript->SetScriptSite(&g_iActiveScriptSite),
"IActiveScript::SetScriptSite()");
// Give the engine a chance to initialize itself...
HRVERIFY(m_iActiveScriptParse->InitNew(),
"IActiveScriptParse::InitNew()");
// Add a root-level item to the engine's name space...
HRVERIFY(m_iActiveScript->AddNamedItem(L"MyObject",
SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE),
"IActiveScript::AddNamedItem()");
// Get script code...
CString csScriptText;
m_edit1.GetWindowText(csScriptText);
// Parse the code scriptlet...
EXCEPINFO ei;
BSTR pParseText = csScriptText.AllocSysString();
m_iActiveScriptParse->ParseScriptText(pParseText, L"MyObject", NULL,
NULL, 0, 0, 0L, NULL, &ei);
// Set the engine state. This line actually triggers the execution
// of the script.
m_iActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED);
// Release engine...
m_iActiveScriptParse->Release();
m_iActiveScript->Release();
}