Надругательство над С++. Пожалуйста, не бейте меня.
От: _Winnie Россия C++.freerun
Дата: 21.11.04 12:52
Оценка: 75 (11) :))) :))) :))

#include <map>
#include <sstream>
#include <string>

using std::string;

struct VarValue
{
  std::string str;

  VarValue() {}

  template <class T> operator T() 
  { 
    T x;
    std::istringstream stream(str);
    stream >> x;
    return x;
  }

  template <class T>  void Assign(T x)
  {
    std::ostringstream stream;
    stream << x;
    str = stream.str();
  }

  template <class T> VarValue(T x)
  {
    Assign(x);
  }

  template <class T> VarValue &operator=(T x)
  {
    Assign(x);
    return *this;
  }

  //для большей путаницы можно другие операторы определить.
};

std::map<std::string, VarValue> variables_;
#define $(var) (variables_[#var])

#include <iostream>








//использование

int main()
{
  $(hello) = "test";
  $(world) = 1;
  $(other_var) = int($(world)) + 10;

  std::cout << (string)$(hello) + (string)$(other_var);
}
Правильно работающая программа — просто частный случай Undefined Behavior
Re: Надругательство над С++. Пожалуйста, не бейте меня.
От: yxiie Украина www.enkord.com
Дата: 21.11.04 14:45
Оценка: :)
Здравствуйте, _Winnie, Вы писали:

_W>//использование

_W>int main()
_W>{
_W>  $(hello) = "test";
_W>  $(world) = 1;
_W>  $(other_var) = int($(world)) + 10;

_W>  std::cout << (string)$(hello) + (string)$(other_var);
_W>}


если ты ще eval к С++ прикрутишь, я буду хлопать стоя
... << RSDN@Home 1.1.3 stable >>
Re[2]: Надругательство над С++. Пожалуйста, не бейте меня.
От: _Winnie Россия C++.freerun
Дата: 23.11.04 01:28
Оценка: 10 (2)
Здравствуйте, yxiie, Вы писали:

Y>Здравствуйте, _Winnie, Вы писали:

Y>если ты ще eval к С++ прикрутишь, я буду хлопать стоя
С перлом дела не имел, до такой штуки как eval не дошел

Можно было бы скомпилировать не dll, а exe, и звать не функцию из dll, а целиком программу.
Но если надо часто звать, то выгодней dll — почти без накладных расходов, оптимизированый С++ом код.

Я слышал, что некоторые таким образом делали "Скрипты на С++" в своих играх.

вот пример общения с моей программой:

c:\projects\test2\test_dll_eval>exe.exe
enter function 'F': (type "#end" to run function)
#include <windows.h>
#include <string>
int F(std::string message) { return MessageBox(0, message.c_str(), message.c_str(), MB_OK); } //показываю пользователю MessageBox
#end
dll.cpp
dll.cpp(47) : warning C4273: 'StringCat' : inconsistent dll linkage
   Creating library dll.lib and object dll.exp
enter parameter for function:
hello,world
result of invocation: 1
enter function 'F': (type "#end" to run function)
#include <math.h>
float F(float rrr) { return sqrtf(rrr); }
#end
dll.cpp
dll.cpp(47) : warning C4273: 'StringCat' : inconsistent dll linkage
   Creating library dll.lib and object dll.exp
enter parameter for function:
2
result of invocation: 1.41421
enter function 'F': (type "#end" to run function)




c:\projects\test2\test_dll_eval>exe.exe
enter function 'F': (type "#end" to run function)
int F(int i) { return i+2; }
#end
dll.cpp
dll.cpp(45) : warning C4273: 'StringCat' : inconsistent dll linkage
   Creating library dll.lib and object dll.exp
enter parameter for function:
3
result of invocation: 5
enter function 'F': (type "#end" to run function)
^C


Это код, наверное, довольно некачественный — какой-то непонятный warning.
И у меня глаза слыпаются, так что прошу простить за допущенные небрежности.

файл exe.cpp


/*
cl /I%BOOST% /EHsc exe.cpp dll.lib 
*/

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <string>

using std::string;

typedef const char *(__cdecl *pfStringCat)(const char *s);
pfStringCat StringCat;

#include <iostream>
#include <fstream>
#include <iterator>

string GetProgram()
{
    std::cout <<"enter function 'F': (type \"#end\" to run function)\n";
    string program, line;
    do 
    {
        (program += line) += '\n';
        std::getline(std::cin, line);
    } while (line != "#end");
    return program;
}

#include <process.h>

void CompileProgram(const string &program)
{
    std::ifstream dll_tail_stream("dll_tail.cpp");
    if (!dll_tail_stream)
        std::cerr <<"can't open file dll_tail.cpp\n";
    string dll_tail;
    for (;;)
    {
        int c = dll_tail_stream.get();
        if (c == EOF)
            break;
        dll_tail += char(c); 
    }

    {
        std::ofstream dll_source("dll.cpp");
        dll_source << program << dll_tail;
    }

    if (0 != system("cl /EHsc dll.cpp /link /dll kernel32.lib user32.lib gdi32.lib /nologo /implib:dll.lib /out:dll.dll"))
    {
        std::cout <<"can't compile program\n";
    }
}

void Run(const string &param)
{
    struct Dll
    {
        HINSTANCE h;
        Dll() { h = LoadLibrary("dll.dll"); }
        ~Dll() { if(h) FreeLibrary(h); }
    } dll;

    if (!dll.h)
    {
        std::cout <<"LoadLibrary failed"; 
        return;
    }
        
    StringCat = (pfStringCat)GetProcAddress(dll.h, "StringCat");
    if (!StringCat)
    {
        std::cout <<"GetProcAddress failed"; 
        return;
    }

    std::cout <<StringCat(param.c_str()) <<'\n';
}


int main()
{
    for (;;)
    {
        CompileProgram(GetProgram());
        string param;
        std::cout <<"enter parameter for function:\n";
        std::cin >> param; 
        std::cout <<"result of invocation: ";
        Run(param);
    }

}


файл dll_tail.cpp

//DLL thunk template


#include <string>
#include <sstream>
#include <stdexcept>
#include <iostream>

using std::string;

template <class R, class P>
string StringMouse(string s)
{
    P p;
    std::istringstream param(s);
    if (!(param >> p))
        throw std::runtime_error("can't convert " + s + "to type " + typeid(P).name());

    R r = F(p);

    std::ostringstream result;
    result << r;
    return result.str();
}

// выводим тип параметра и возвращаемого значения, исходя из типа указателя на функцию F
// возвращам указатель на функцию, которая конвертит строки туда-сюда, вызывая при этом F 
template <class R, class P> 
string (*StringDog(R(*)(P)))(string)
{
  return &StringMouse<R, P>;
}
//
//extern "C" __declspec(dllimport) 
//const char *StringCat(const char *s);

extern "C" __declspec(dllimport) 
const char *__cdecl StringCat(const char *s);

extern "C" 
const char *__cdecl StringCat(const char *s)
try
{
  static string result; //опасно, да. не надо так делать. Ну не надо...
  result = StringDog(F)(s);
  return result.c_str();
}
catch (std::exception &err)
{
    std::cout << err.what();
    return "";
}
Правильно работающая программа — просто частный случай Undefined Behavior
Re: Надругательство над С++. Пожалуйста, не бейте меня.
От: ch00k  
Дата: 23.11.04 07:20
Оценка:
boost::any ?
Re[3]: Надругательство над С++. Пожалуйста, не бейте меня.
От: yxiie Украина www.enkord.com
Дата: 23.11.04 10:52
Оценка:
Здравствуйте, _Winnie, Вы писали:

...

мда... не думал я, что ты ТАКОЙ извращенец
... << RSDN@Home 1.1.3 stable >>
Re[3]: Надругательство над С++. Пожалуйста, не бейте меня.
От: Centaur Россия  
Дата: 23.11.04 20:45
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>Можно было бы скомпилировать не dll, а exe, и звать не функцию из dll, а целиком программу.

_W>Но если надо часто звать, то выгодней dll — почти без накладных расходов, оптимизированый С++ом код.

Компилируемый из пользовательского ввода исполняемый код… Брррр. В таких вещах нужно очень сильно о безопасности подумать.
Re[4]: Надругательство над С++. Пожалуйста, не бейте меня.
От: yxiie Украина www.enkord.com
Дата: 23.11.04 21:41
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Здравствуйте, _Winnie, Вы писали:


_W>>Можно было бы скомпилировать не dll, а exe, и звать не функцию из dll, а целиком программу.

_W>>Но если надо часто звать, то выгодней dll — почти без накладных расходов, оптимизированый С++ом код.

C>Компилируемый из пользовательского ввода исполняемый код… Брррр. В таких вещах нужно очень сильно о безопасности подумать.


да, вся эта ветка, читый прикол, никто не призывает к практическому применению этой жути
в общем мое мнение такое: эту ветку давно пора в "юмор".
... << RSDN@Home 1.1.3 stable >>
Re[5]: Надругательство над С++. Пожалуйста, не бейте меня.
От: _Winnie Россия C++.freerun
Дата: 23.11.04 21:55
Оценка:
Здравствуйте, yxiie, Вы писали:

Y>да, вся эта ветка, читый прикол, никто не призывает к практическому применению этой жути

Y>в общем мое мнение такое: эту ветку давно пора в "юмор".

Могут не понять
1-й пост, да — сферический конь, по-сути. А второй — уже вполне пригодная для использования вещь...
Правильно работающая программа — просто частный случай Undefined Behavior
Re[4]: Надругательство над С++. Пожалуйста, не бейте меня.
От: _Winnie Россия C++.freerun
Дата: 23.11.04 21:58
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Здравствуйте, _Winnie, Вы писали:


_W>>Но если надо часто звать, то выгодней dll — почти без накладных расходов, оптимизированый С++ом код.


C>Компилируемый из пользовательского ввода исполняемый код… Брррр. В таких вещах нужно очень сильно о безопасности подумать.

Зависит от области применения и задач.
Правильно работающая программа — просто частный случай Undefined Behavior
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.