2010-08-06 17 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調用時如上所示傳遞。

現在我該如何將堆空指針轉換爲堆棧類型對象。不知何故,如果我得到foo的參數a_myStruct的地址,我可以用void*指向那個位置,但是我不能取消引用void*,以便它被轉換成MyStruct類型的對象。

任何其他解決問題的方法?就像在C++中一樣,我們也可以在運行時確定類型。


我有一個問題,在運行時調用函數在C++中可能有簽名具有完全未在這些類型的編譯時間。但細節已知用戶定義類型提供給我的(正如我破譯來自類型庫或DIA SDK的某些類型的詳細信息)。但主要問題是現在我想在運行時調用這些函數。在編譯時,我只有函數地址和用戶定義類型的詳細信息,哪些對象或指針參與了該函數簽名的參數。現在,如果我想在運行時調用該函數,我需要在運行時首先通過在堆上創建臨時塊並用該數據填充該塊來填充該類型。我具有該類型的所有細節。

現在的問題是我不知道該函數將參數作爲該類型的指針,我有詳細信息可用或該參數恰好是該類型的堆棧對象。如果我有指向該類型的指針沒有問題,但是如果對象存在,則在運行時調用該函數時遇到很大問題。

+4

你想在這裏做什麼?無論如何,此代碼絕對沒有意義。也許你應該向後退一步,並解釋你正試圖解決的真正問題。 – 2010-08-06 19:39:31

+0

嘗試將結構轉換爲指向其用於成員變量的類型的指針意味着您不知道結構如何工作。我和詹姆斯在一起。這段代碼沒有任何意義。 – 2010-08-06 19:43:42

+0

我懷疑OP試圖修改每種情況下被投射到的類型結構的成員。爲什麼仍然完全困惑我。 – 2010-08-06 19:46:44

回答

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是一個完整的類型,它在編譯時是不知道的。所以一個char數組在這裏不起作用。 – Hassan 2010-08-06 20:10:47

1

我必須承認,即使有您提供的附加信息,我也不完全理解您的問題。但讓我說兩句一般對棧和堆和C++:

參數如何被傳遞給函數是一個特別的C++編譯器,即實現細節。這可以從一個C++編譯器到下一個不同。將參數傳遞給函數的方法稱爲調用約定。一些編譯器既不使用堆棧也不使用堆來傳遞參數。如果可能的話,他們使用CPU寄存器。 (WATCOM的C++編譯器/是有利於寄存器將參數傳遞給功能的編譯器的一個顯着的例子。)

這意味着,任何C++編譯器可創建不二進制兼容到其他C二進制++編譯器。 (C++語言標準沒有規定編譯輸出的二進制標準,因此不同的編譯器可能會產生二進制不兼容的輸出;但是任何C++編譯器都保證至少與自身是二進制兼容的。)因此,如果您想使用庫,你有三種選擇:

  • 選擇一個二進制文件,它與你特定的C++編譯器和鏈接器相匹配;

  • 使用您的編譯器自己編譯庫源代碼;或者

  • 選擇一個符合特定二進制標準(如DLL庫格式或Microsoft COM標準)的庫二進制文件,這也是C++編譯器和鏈接器所支持的。

總之,你對棧對象與堆對象的問題沒有意義。在C++中沒有這樣的「堆棧對象」。你沒有明確的控制如何將一個參數傳遞給一個函數,因爲這是C++編譯器自己決定怎麼做的事情 - 雖然似乎存在關鍵字和特殊語法來控制這種行爲(即引用,指針,以及autoregister關鍵字),他們一般將不會保證將以特定方式傳遞參數。如果你知道一個特別是編譯器好,那麼你可能會推導出參數傳遞如何與這個編譯器一起工作......但是一般是,你不能—並且不應該有—知道這個機制。

P.S。:我忘了提及術語「堆棧對象」在參數傳遞方面不僅沒有意義。更一般地說,根本沒有辦法告訴編譯器在堆棧上分配一個對象。雖然局部變量通常會在堆棧中分配,但是對此無法保證。我想這就是你選擇逃避彙編語言的原因。然後,您可以明確指定pushpop值來自堆棧(由CPU管理)。

相關問題