Передать массив в функцию по значению
От:
stas19t
Дата: 01.09.10 06:33
Оценка:
Добрый день!
Есть потребность вызывать функции с неизвестным числом параметров.
Я делаю это так:
// cast pointer to delegate
typedef void* (*AnyFunc)(...);
AnyFunc userFunc = AnyFunc(funcPtr);
Параметры для userFunc у меня в массиве.
Чтобы вызвать userFunc, я использую switch:
// call user defined function
void* result;
switch (argsCount)
{
case 0:
result = userFunc();
break;
case 1:
result = userFunc(args[0]);
break;
case 2:
result = userFunc(args[0], args[1]);
break;
.... и т.д.
Этот код работает. Но хотелось бы обойтись без switch на 255 кейсов.
Реальные функции на вход могут принимать различное число параметров. Например, как-то так:
int MyFunc1(int p1, int p2) { return p1+p2; } // изменить эти функции возможности нет.
int MyFunc2(int p1) { return p1*p1; }
Если передавать тупо массив вот так:
result = userFunc(args);
то, насколько я понимаю, передается не сам массив, а ссылка на него.
Поэтому у меня ничего не работает.
Посоветуйте пожалуйста, возможно ли как-то красиво решить эту проблему?
Спасибо!
п.с.: понадобилось сделать такой изврат, т.к. нужно обращаться к user defined functions созданных для excel. функции находятся в dll. на врод они на самом деле принимают переменное число указателей на struct XLOPER12, а не int, как в моих примерах.
Re: Передать массив в функцию по значению
От:
stas19t
Дата: 01.09.10 08:17
Оценка:
Так тоже не получается:
public struct Array {
int el[2];
} ar;
ar.el[0] = 1;
ar.el[1] = 2;
void* result = userFunc(ar);
В окне Disassembly выглядит это вот так:
public struct Array {
int el[3];
} ar;
ar.el[1] = 1;
0000015e mov dword ptr [rsp+000000F4h],1
ar.el[2] = 2;
00000169 mov dword ptr [rsp+000000F8h],2
void* result = userFunc(ar);
00000174 mov r11,83CD720h
0000017e mov r10,qword ptr [rsp+28h]
00000183 lea rcx,[rsp+000000F0h]
0000018b mov rax,qword ptr [rcx]
0000018e mov qword ptr [rsp+60h],rax
00000193 mov eax,dword ptr [rcx+8]
00000196 mov dword ptr [rsp+68h],eax
0000019a lea rcx,[rsp+60h]
0000019f call 000000000867A524
Re[2]: Передать массив в функцию по значению
От:
stas19t
Дата: 01.09.10 08:22
Оценка:
Здравствуйте, stas19t, Вы писали:
S>Так тоже не получается:
S>S> public struct Array {
S> int el[2];
S> } ar;
S> ar.el[0] = 1;
S> ar.el[1] = 2;
S> void* result = userFunc(ar);
S>
S>В окне Disassembly выглядит это вот так:
S>S> public struct Array {
S> int el[3];
S> } ar;
S> ar.el[1] = 1;
S>0000015e mov dword ptr [rsp+000000F4h],1
S> ar.el[2] = 2;
S>00000169 mov dword ptr [rsp+000000F8h],2
S> void* result = userFunc(ar);
S>00000174 mov r11,83CD720h
S>0000017e mov r10,qword ptr [rsp+28h]
S>00000183 lea rcx,[rsp+000000F0h]
S>0000018b mov rax,qword ptr [rcx]
S>0000018e mov qword ptr [rsp+60h],rax
S>00000193 mov eax,dword ptr [rcx+8]
S>00000196 mov dword ptr [rsp+68h],eax
S>0000019a lea rcx,[rsp+60h]
S>0000019f call 000000000867A524
S>
Для сравнения:
void* result = userFunc(ar.el[1], ar.el[2]);
00000183 mov ecx,dword ptr [rsp+000000E4h]
0000018a mov edx,dword ptr [rsp+000000E8h]
00000191 mov r11,822FE20h
0000019b mov r10,qword ptr [rsp+28h]
000001a0 call 000000000868A524
Re[2]: Передать массив в функцию по значению
Здравствуйте, stas19t, Вы писали:
S>Так тоже не получается:
S>S> public struct Array {
S> int el[2];
S> } ar;
S>
Друг, это не С и не С++
Re: Передать массив в функцию по значению
От:
szag
Дата: 01.09.10 08:22
Оценка:
Здравствуйте, stas19t, Вы писали:
S>Добрый день!
S>Есть потребность вызывать функции с неизвестным числом параметров.
была таже проблема, мне помог
вот такой вариант.Автор: Sni4ok Дата: 06.08.10
Re: Передать массив в функцию по значению
Здравствуйте, stas19t, Вы писали:
S>Добрый день!
S>Есть потребность вызывать функции с неизвестным числом параметров.
используйте boost.fusion, функцию invoke
In Zen We Trust
Re: Передать массив в функцию по значению
Здравствуйте, stas19t, Вы писали:
S>Если передавать тупо массив вот так:
S>S>result = userFunc(args);
S>
S>то, насколько я понимаю, передается не сам массив, а ссылка на него.
Передается, конечно, указатель, но не в этом дело. Передача по значению, если бы она и была, ничем бы не помогла.
Рассмотрим, как вызов происходит. Аргументы засылаются в стек, после чего происходит переход по адресу функции.
2 аргумента — 2 команды push, 4 -вргумента — 4 push.
Так что массив здесь вообще не поможет.
S>Поэтому у меня ничего не работает.
S>Посоветуйте пожалуйста, возможно ли как-то красиво решить эту проблему?
С помощью асмовской вставки можно. Заслать эти аргументы в стек и вызвать как функцию без аргументов.
With best regards
Pavel Dvorkin
Re[3]: Передать массив в функцию по значению
От:
stas19t
Дата: 01.09.10 17:16
Оценка:
Здравствуйте, Ytz, Вы писали:
Ytz>Здравствуйте, stas19t, Вы писали:
S>>Так тоже не получается:
S>>S>> public struct Array {
S>> int el[2];
S>> } ar;
S>>
Ytz>Друг, это не С и не С++
Да
. Спалился. На самом деле пишу на unsafe managed c++.
Re: Передать массив в функцию по значению
От:
stas19t
Дата: 01.09.10 17:19
Оценка:
szag, Abyx, Pavel Dvorkin!
Спасибо за советы!
С boost я знаком слабо. С asm тоже поверхностно.
Видимо пока оставлю switch и положу себе на стек этот вопрос, т.к. очевидно он потребует вложений времени несколько больше чем ожидалось.
Постараюсь разобраться в вопросе. Отпишусь.
Re[2]: Передать массив в функцию по значению
От:
igna
Дата: 02.09.10 11:08
Оценка:
Здравствуйте, stas19t, Вы писали:
S>С boost я знаком слабо.
Прочитал
совет of AbyxАвтор: Abyx Дата: 01.09.10
, попробовал, работает:
#include <iostream>
using namespace std;
#include <boost/fusion/include/array.hpp>
#include <boost/fusion/include/invoke.hpp>
void f(int i, int j, int k)
{
cout << i << ' ' << j << ' ' << k << '\n' ;
}
int main()
{
int a[] = { 1, 2, 3 };
boost::fusion::invoke(f, a);
}
Ранее Fusion не использовал, так что может и со "слабым знакомством" пойдет.
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить