2012-03-30 32 views
5

Có một hàm API tồn tại mà không chỉ cho phép các plugin (DLL) để nhận ba tham số và thực hiện một số hành động:Cách sửa đổi nội dung của biến ban đầu được chuyển bằng giá trị?

int ProcessMe(int nCommand, unsigned int wParam, long lParam); 

Bây giờ, từ chương trình chính (exe), muốn vượt qua hai biến để các plugin, và yêu cầu plugin để sửa đổi nội dung của họ, và chương trình chính sẽ đọc chúng một lần nữa, để thực hiện một số nhiệm vụ.

Câu hỏi của tôi là, từ hàm trên, tôi có thể thực hiện việc này mà không thay đổi các tham số chức năng không?

Ví dụ:

int ProcessMe(int nCommand, unsigned int wParam, long lParam) 
{ 
    // modify the parameters// 
    return 0; 
} 

int main() 
{ 
    BOOL bSave = TRUE; 
    int nOption = 0; 
    ProcessMe(0, (unsigned int)(&bSave), (long)(&nOption)); 
    if(FALSE==bSave) 
    printf("bSave is modified!"); 
    return 1; 
} 
+1

Không. Bạn cần phải vượt qua tham chiếu mà bạn không thể thực hiện mà không thay đổi API. Bạn sẽ phải thực hiện lại giao diện bằng con trỏ, hoặc học cách sống mà không có. – tbert

+0

Đáng buồn là tôi không được phép thay đổi giao diện vì hiện tại có nhiều DLL khác đang chạy với exe sử dụng giao diện tương tự .... mối quan tâm tương thích ngược cho tôi: ( – wengseng

+1

Điều này không có ý nghĩa. Bạn có thể khai báo một hàm mới –

Trả lời

5

Nơi các biến thay đổi trong một cấu trúc và vượt qua con trỏ đến sturuct để cắm trong:

struct MyStruct 
{ 
    BOOL bSave; 
    int nOption; 
}; 

int ProcessMe(int nCommand, unsigned int wParam, long lParam) 
{ 
    ((MyStruct*)lParam)->nOption = ...; 
    return 0; 
} 

Sử dụng nó như thế này:

int main() 
{ 
    MyStruct struct; 
    struct.bSave = TRUE; 
    struct.nOption = 0; 
    ProcessMe(0, 0, (long)(&struct)); 
    if(FALSE==struct.bSave) 
    printf("bSave is modified!"); 
    return 1; 
} 

Nói đúng cách đây là hành vi không xác định. Bạn cần phải kiểm tra, cho dù nó hoạt động trên nền tảng của bạn.

Lưu ý: Tôi đã sử dụng cấu trúc ở đây, bởi vì theo cách này bạn cũng có thể chuyển nhiều biến hơn hoặc các biến lớn hơn, chẳng hạn như tăng gấp đôi đến hàm.

+0

Sai, điều này sẽ không sửa đổi các thông số ban đầu. 'wParam' sẽ vẫn giống nhau. –

+2

@LuchianGrigore - tất nhiên! Mục đích là sửa đổi nội dung của cấu trúc. – Henrik

+0

Cấu trúc nào? Không có cấu trúc trong mã của anh ta. Câu trả lời của bạn trả lời một câu hỏi hoàn toàn khác. –

3

Không, không có cách nào để làm điều đó.

Truyền theo giá trị nghĩa là bản sao của bản gốc được tạo. Trong phạm vi phương thức, bạn sẽ không có thông tin về các biến ban đầu.

Bạn cần phải vượt qua bằng tham chiếu hoặc theo giá trị.

+0

Điều này không chính xác. Mặc dù bạn không thể thực hiện nó theo cách an toàn, bạn có thể thực hiện nó bằng cách diễn giải lại nội dung của 'lParam'. Điều này trong thực tế xảy ra rất nhiều trong Win32 API. Henrik đã cho thấy một giải pháp hoạt động. – AlefSin

+0

@AlefSin dereferencing NULL con trỏ cũng xảy ra trong Win32 API. Đó là lý do tại sao chúng tôi có một tiêu chuẩn để hướng dẫn chúng tôi, không phải tài liệu MSDN. –

+3

Tôi biết nó không an toàn, và tôi nói vậy. Điều này tất cả bắt nguồn từ thực tế là một số API cũ hơn được thiết kế trong một thời đại khi các lập trình viên C không quan tâm nhiều về an toàn kiểu. Khi bạn không thể thay đổi mã của API, bạn sẽ phải sử dụng giải pháp xấu, không an toàn, không di động và có thể nguy hiểm. – AlefSin

1

Hãy thử điều này ... nó CÓ THỂ !!!

bao gồm

int ProcessMe (int nCommand, unsigned int wParam, lParam dài)

{

int *nCommand_ptr = (int*)nCommand; 
unsigned int *wParam_ptr = (unsigned int*)wParam; 
long *lParam_ptr = (long*)lParam; 
*nCommand_ptr = 10; 
*wParam_ptr = 10; 
*lParam_ptr = 10; 
return 0; 

}

int main() {

int nCommand = 5; 
unsigned int wParam = 5; 
long lParam = 5; 
printf("\n %d %u %lu",nCommand,wParam,lParam); 
ProcessMe((int)&nCommand,(unsigned int)&wParam,(long)&lParam); 
printf("\n %d %u %lu",nCommand,wParam,lParam); 
return 0; 

}

Output:

$> g ++ passbyref.cc

$> ./ a.ra

10 10 10 $>

1

Biên soạn cho 32 nền tảng bit bạn có thể cast vào con trỏ tham số:

#include <stdio.h> 
typedef int BOOL; 
#define FALSE 0 
#define TRUE 1 

int ProcessMe(int nCommand, unsigned int wParam, long lParam) 
{ 
    // cast to match what you passed in 
    *((BOOL*)wParam) = FALSE; 
    return 0; 
} 

int cast_arguments_main(int, char **) 
{ 
    BOOL bSave = TRUE; 
    int nOption = 0; 
    ProcessMe(0, (unsigned int)(&bSave), (long)(&nOption)); 
    if(FALSE==bSave) 
    printf("bSave is modified!"); 
    return 1; 
} 

Trên một nền tảng 64 bit trình biên dịch phàn nàn về không thể đại diện cho con trỏ:

cast_arguments.cpp:17:37: error: cast from ‘BOOL*’ to ‘unsigned int’ loses precision 

Tôi phải thay đổi Khai báo tham số unsigned int wParam thành unsigned long wParam và thay đổi tương tự tại điểm gọi: ProcessMe(0, (unsigned long)(&bSave), (long)(&nOption)); nhưng sau đó bạn có thể chỉ cần khai báo đúng loại cho tham số của mình, là BOOL *. Do đó tính khả thi phụ thuộc vào kiến ​​trúc máy mục tiêu của bạn ...

+0

Trên Windows 64 bit (đây là nơi tên 'lParam' bật lên nhiều nhất), loại lParam không phải là' long'. Trên thực tế, ông có lẽ chỉ nên sử dụng 'intptr_t' để bắt đầu. –

Các vấn đề liên quan