Как изменить содержимое исходной переменной, которая передается по значению? - PullRequest
5 голосов
/ 30 марта 2012

Существует существующая функция API, которая позволяет плагину (DLL) получать только три параметра и выполнять некоторые действия:

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

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

Мой вопрос заключается в том, могу ли я выполнить эту функцию без измененияпараметры функции?

Пример:

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

Ответы [ 4 ]

5 голосов
/ 30 марта 2012

Поместите переменные для изменения в структуру и передайте указатель на структуру в плагин:

struct MyStruct
{
    BOOL bSave;
    int nOption;
};

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

Используйте это так:

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

Строго говоря, это неопределенное поведение. Вам нужно проверить, работает ли он на вашей платформе.

Примечание: я использовал структуру здесь, потому что таким образом вы также можете передавать в функцию больше переменных или больших переменных, таких как double.

3 голосов
/ 30 марта 2012

Нет, сделать это невозможно.

Передача по значению означает, что создаются копии оригинальных.В области действия метода у вас не будет никакой информации об исходных переменных.

Вам необходимо либо передать по ссылке, либо по значению.

1 голос
/ 30 марта 2012

Компиляция для 32-битной платформы вы можете привести к указателю параметра:

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

На 64-битной платформе компилятор жалуется на невозможность представления указателя:

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

Мне пришлось изменить объявление параметра unsigned int wParam на unsigned long wParam и аналогичные изменения в точке вызова: ProcessMe(0, (unsigned long)(&bSave), (long)(&nOption));, но тогда вы могли бы просто объявить правильный тип для вашего параметра, равный BOOL *.Таким образом, выполнимость зависит от архитектуры вашей целевой машины ...

1 голос
/ 30 марта 2012

Попробуйте это ... это ВОЗМОЖНО !!!

include

int ProcessMe (int nCommand, unsigned int wParam, long 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 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;

}

Вывод:

$> g ++ passbyref.cc

$> ./ a.out

5 5 5

10 10 10 $>

...