2010-08-06 2 views
0

У меня есть сложная проблема, которую нужно решить, поскольку я застрял и не нашел никакого способа решить эту проблему. Вот кодВызвать функцию, беря объект стека в качестве аргумента с данными на основе кучи

struct MyStruct 
{ 
    int x;  
    float y; 
    char c; 
}; 

void foo(MyStruct a_myStruct); 

int _tmain(int argc, _TCHAR* argv[])  
{ 
    void *pMyStruct = malloc(sizeof(MyStruct)); 
    int* pInt = (int*)pMyStruct; 

    *pInt = 10;  
    pInt++; 

    float *pFloat = (float*)pInt;  
    *pFloat = 2.545; 
    pFloat++; 

    char *pChar = (char*)pFloat; 
    *pChar = 'c'; 

    _asm 
    { 
     pMyStruct 
     call foo 
    } 

    return 0; 
} 

void foo(MyStruct a_myStruct) 
{ 
} 

Здесь вы можете увидеть, что foo работает на объекте в стеке и ожидает объект стека будет отображаться, когда foo вызывается. Но, к сожалению, тип MyStruct не известен во время компиляции, поэтому мне нужно создать блоки памяти, а затем во время выполнения данные заполняются внутри этого блока, который затем передается при вызове foo с asm, как показано выше.

Теперь как преобразовать указатель пустоты кучи в объект типа стека. Так или иначе, если я получаю адрес аргумента a_myStructfoo, я могу указать void* на это место, но снова не могу разыменовать void*, чтобы он преобразовывался в объект типа MyStruct.

Любой другой способ решения проблемы? Как и в C++, мы можем определить тип во время выполнения.


У меня есть проблема для вызова функции во время выполнения в C++, которые могут иметь подписи с полным определенным пользователем типов, которые не известны на этапе компиляции time.But детали этих типов доступны для меня (как я расшифровала детали определенного типа из библиотеки типов или из DIA SDK). Но главная проблема - теперь я хочу назвать эти функции во время выполнения. Во время компиляции у меня просто есть адрес функции и детали пользовательского типа, какой объект или указатель участвует в качестве аргумента этой сигнатуры функции. Теперь, если я хочу вызвать эту функцию во время выполнения, мне нужно сначала заполнить этот тип во время выполнения, создав временный блок в куче и заполнив этот блок данными. У меня есть все данные этого типа.

Теперь проблема заключается в том, что я не знаю, что функция принимает аргумент в качестве указателя того типа, у которого у меня есть данные, или этот аргумент точно является объектом стека этого типа. Если у меня есть указатель на этот тип, проблема не возникает, но если объект там, у меня есть большая проблема для вызова этой функции во время выполнения.

+4

Что вы пытаетесь сделать здесь? Этот код не имеет абсолютно никакого смысла.Возможно, вы должны сделать шаг назад и объяснить реальную проблему, которую вы пытаетесь решить. –

+0

Попытка применить структуру к указателям к типам, которые она имеет для переменных-членов, подразумевает, что вы не знаете, как работают структуры. Я с Джеймсом на этом. Этот код не имеет никакого смысла. –

+0

Я подозреваю, что ОП пытается изменить член структуры того типа, к которому его бросают в каждом случае. Почему меня все еще озадачивает. –

ответ

1

Я не понимаю, почему вы думаете, что вам нужно заполнить свою структуру так, как вы показываете, но независимо от того, что вы делаете это неправильно.

Он должен был бы быть больше как:

int* pInt = (int*)pMyStruct; 
*pInt++ = 10; 
float *pFloat = (float*)pInt; 
*pFloat++ = 2.545; 
char *pChar = (char*)pFloat; 
*pChar = 'c'; 

Который полностью зависят от платформы, и, вероятно, не будет работать правильно либо.

Предполагая, что вы получите MyStruct заселена, Одно простое решение для вызова foo бы изменить его к этому: к

void foo(MyStruct* pMyStruct); 

Если это не представляется возможным, вам нужно скопировать его в стек. Что-то вроде

char rawBytes[sizeof(MyStruct)]; 
memcpy(&rawBytes,MyStruct,sizeof(MyStruct)); 
foo(*(MyStruct*)rawBytes)` 

может работать. Или нет, поскольку вы не знаете MyStruct во время компиляции, компилятор не может создать код манипуляции стеком.

Я предполагаю, что вы знаете во время работы, как большой MyStruct.Таким образом, это должно быть больше, как это:

_asm{ 
    //pseudo-assembly 
    cx = numBytesInMyStruct 
    bx = pointerToYourFakeMyStruct 
    loop cx 
    push *bx++ 
    call foo 
} 
+0

Я думаю, что копирование данных в стек может помочь, но, к сожалению, здесь не получается работать. Он не может правильно копировать. Более того, MyStruct - это полный тип, который неизвестен во время компиляции. Поэтому массив символов здесь не работает. – Hassan

1

Я должен признать, что даже с дополнительной информацией, предоставленной вами, я не полностью понимаю ваш вопрос. Но позвольте мне сказать, что-то общее о стеке и в куче и C++:

Как аргумент получает переданные функции является деталью реализации компилятора конкретного C++, то есть. это может варьироваться от одного компилятора C++ к другому. Метод, по которому передаются аргументы в функции, называется соглашение о созыве. Некоторые компиляторы не используют ни стек, ни кучу для передачи аргументов; вместо этого они используют регистры CPU, если это возможно. (Компилятор C++ Watcom является/был яркий пример компилятора, который выскажется регистрами для передачи аргументов в функцию.)

Это означает, что любой компилятор C++ может создавать исполняемые файлы, которые не двоичной совместимости на другие C++ компилятор. (Стандарт языка C++ не предписывает двоичный стандарт для скомпилированного вывода, поэтому разные компиляторы могут генерировать двоично-несовместимый вывод, но любой компилятор C++ гарантированно совместим с двоичными файлами, по крайней мере, для себя.) Таким образом, если вы хотите использовать библиотеки, у вас есть три возможности:

  • выбрать двоичный файл, который соответствует вашему конкретному компилятору и компоновщику на C++;

  • скомпилируйте источники библиотек самостоятельно, используя ваш компилятор; или

  • выберите бинарный файл библиотеки, который придерживается определенного двоичного стандарта (например, формата библиотеки DLL или стандартного COM-стандарта Microsoft), который также поддерживается вашим компилятором и компоновщиком C++.

В заключении ваш вопрос об объекте стеки против объекта кучи не имеет смысла. В C++ нет такой вещи, как «объект стека». У вас нет явного контроля того, как аргумент передается функции, потому что это то, что компилятор C++ сам решает, как это сделать - и, хотя для управления этим поведением существуют ключевые слова и специальный синтаксис (а именно, ссылки, указатели, а также ключевые слова и register), они обычно не гарантируют, что параметр будет передан определенным образом. Если вы знаете один конкретный компилятор, то вы, возможно, сможете определить, как работает передача параметров с этим компилятором ... но обычно, вы не можете — и не должны — знать об этом механизме.

P.S .: Я забыл упомянуть, что термин «объект стека» не просто бессмыслен в терминах передачи параметров. Даже в более общем плане просто не существует способа сказать компилятору выделить объект в стеке. В то время как локальные переменные обычно будут выделены в стеке,, для этого нет никакой гарантии. Полагаю, поэтому вы выбрали выход на ассемблер. Затем вы можете явно указать push и pop значения в стек/из стека (как управляется ЦП).

Смежные вопросы