2012-03-30 17 views
5

Jest istniejąca funkcja API, które nie tylko pozwalają wtyczki (DLL), aby otrzymać trzy parametry i wykonać pewne działania:Jak zmodyfikować zawartość oryginalnej zmiennej przekazywanej przez wartość?

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

Teraz z głównego programu (exe), chciałby przekazać dwie zmienne wtyczkę i wymagają wtyczki do modyfikowania ich zawartości, a program główny odczyta je ponownie, aby wykonać pewne zadanie.

Moje pytanie brzmi, czy z powyższej funkcji mogę to zrobić, bez zmiany parametrów funkcji?

przykład:

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

Nie. Musisz podać referencję, której nie możesz zrobić bez zmiany interfejsu API. Musisz albo ponownie wdrożyć interfejs za pomocą wskaźników, albo nauczyć się żyć bez niego. – tbert

+0

Niestety nie mam uprawnień do zmiany interfejsu, ponieważ obecnie istnieje wiele innych bibliotek DLL uruchomionych z programem exe przy użyciu podobnego interfejsu .... obawiam się zgodności ze starszymi wersjami :( – wengseng

+1

To nie ma sensu. Funkcja wygrała ' t oczekiwać użycia parametrów do przechowywania wyników, nie są one przeznaczone do wyprowadzania, musisz zadeklarować nową funkcję –

Odpowiedz

5

miejsce zmienne zmodyfikować do struktury i przejść kursorem do sturuct do wtyku w:

struct MyStruct 
{ 
    BOOL bSave; 
    int nOption; 
}; 

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

pomocą tak:

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; 
} 

Ściśle mówiąc jest to niezdefiniowane zachowanie. Musisz sprawdzić, czy działa na twojej platformie.

Uwaga: Użyłem tutaj struktury, ponieważ w ten sposób można również przekazywać więcej zmiennych lub większych zmiennych, takich jak podwójne do funkcji.

+0

Niepoprawnie, to nie zmieni oryginalnych parametrów. 'wParam' nadal będzie taki sam. –

+2

@LuchianGrigore - oczywiście! Zamiarem jest zmodyfikowanie zawartości struktury. – Henrik

+0

Jaką strukturę? W jego kodzie nie ma żadnej struktury. Twoja odpowiedź jest odpowiedzią na zupełnie inne pytanie. –

3

Nie, nie ma sposobu, aby to zrobić.

Przekazywanie według wartości oznacza, że ​​tworzone są kopie oryginalnych. W zakresie metody nie będziesz mieć informacji o oryginalnych zmiennych.

Musisz przekazać jako odniesienie lub według wartości.

+0

To nie jest poprawne. Chociaż nie możesz tego zrobić w sposób bezpieczny, możesz to zrobić, ponownie interpretując zawartość 'lParam'. Tak naprawdę dzieje się to w Win32 API. Henrik już pokazał rozwiązanie, które działa. – AlefSin

+0

@AlefSin dereferencing Wskaźniki NULL również występują w Win32 API. Właśnie dlatego mamy standard, który nas prowadzi, a nie dokumentację MSDN. –

+3

Wiem, że to nie jest bezpieczny rodzaj i powiedziałem to. Wszystko to wynika z faktu, że niektóre starsze API zostały zaprojektowane w erze, w której programista C nie dbał zbytnio o bezpieczeństwo typu. Jeśli nie możesz zmienić kodu interfejsu API, musisz zrezygnować z brzydkiego, niebezpiecznego, nieprzenośnego i potencjalnie niebezpiecznego rozwiązania. – AlefSin

1

Wypróbuj to ... jest MOŻLIWE !!!

obejmują

int ProcessMe (int nCommand unsigned int wParam długo LPARAM)

{

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 główny() {

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; 

}

wyjściowa:

$> g ++ passbyref.cc

$> ./ a.z

10 10 10 $>

1

Kompilacja dla 32 platformy bitów można rzucić do wskaźnika parametr:

#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; 
} 

na platformie 64 bitów kompilator narzeka niemożność przedstawienia wskaźnika:

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

Musiałem zmienić unsigned int wParam deklaracja parametru do unsigned long wParam, i podobna zmiana w punkcie wywołania: ProcessMe(0, (unsigned long)(&bSave), (long)(&nOption)); , ale możesz po prostu zadeklarować odpowiedni typ dla swojego parametru, aby być BOOL *. Tak więc, wykonalność zależy od architektury docelowego komputera ...

+0

W 64-bitowym systemie Windows (gdzie najczęściej pojawia się nazwa 'lParam'), typem lParam nie jest' long'. Właściwie powinien po prostu używać 'intptr_t' na początek. –

Powiązane problemy