C 고수님들, 함수 사이 값 전달 관련 질문입니다.

aeronova의 이미지

안녕하세요,
어떤 함수에 인자로 전달한 것을 다름 함수에 인자를 쓰지 않고 전달하는 방법을 알고 싶습니다.
(global로 인자를 정의하면 되겠지만, 이것이 여의치 않아서요.)

우선 제가 하려고 하는 것을 간단히 설명드리겠습니다.
하는 일은 C로 짜여진 NSGA2와 CFSQP라는 프로그램을 연동해서 사용하려고 합니다. 즉, NSGA2에서 CFSQP를 내부적으로 부르게 됩니다.
(둘다 source는 가지고 있지만 가능하면 source 그 자체를 건드리지 않으려고 합니다.)
두 프로그램을 사용하기 위해서는 각각의 objective를 제가 정의해 주어야 하는데, 문제는 이 objective라는 것들의 함수 signature가 고정되어 있어서, 제가 임의로 인자를 하나 더 추가할 수 없습니다. 그래서 인자 전달 없이 값을 전달 할 방도가 없을까 하는 고민을 하게 되었습니다.

우선, NSGA2라는 C로 짜여진 optimizer에 objective 함수를 정의해 줍니다.

void test_problem (double *xreal, double *xbin, int **gene, double *obj, double *constr)
{
     // 전달해 줄 인자인 xreal을 넘겨줍니다.
    obj[0] = pseudo_objective(xreal);
    return;
}

여기서는 다른 optimizer인 CFSQP를 실행시킵니다.

double* pseudo_objective(double* xreal)
{
   int nparam,nf,nineq,neq,mode,iprint,miter,neqn,nineqn,ncsrl,ncsrn,nfsr,mesh_pts[1],inform;
   double bigbnd,eps,epsneq,udelta;
   double *x,*bl,*bu,*f,*g,*lambda;
   void *cd;
 
   // option settings
   mode=100;   
   iprint=1;
   miter=500;  
   bigbnd=1.e10;
   eps=1.e-8;
   epsneq=0.e0;
   udelta=0.e0;
   nparam=1;  
   nf=1;
   neqn=0;
   nineqn=0;
   nineq=0;
   neq=0;
 
   ncsrl=ncsrn=nfsr=mesh_pts[0]=0;
   bl=(double *)calloc(nparam,sizeof(double));
   bu=(double *)calloc(nparam,sizeof(double));
   x=(double *)calloc(nparam,sizeof(double));
   f=(double *)calloc(nf,sizeof(double));
   g=(double *)calloc(nineq+neq,sizeof(double));
   lambda=(double *)calloc(nineq+neq+nf+nparam,sizeof(double));
 
   bl[0]=0.e0;
   bu[0]=bigbnd; 
   x[0]=0.1e0; 
 
   // 위의 부분은 아래 cfsqp를 부르기 위한 option setting 입니다.
   // 바로 이 부분에서 다른 optimizer를 부릅니다.
   cfsqp(nparam,nf,nfsr,nineqn,nineq,neqn,neq,ncsrl,ncsrn,mesh_pts,
         mode,iprint,miter,&inform,bigbnd,eps,epsneq,udelta,bl,bu,x,
         f,g,lambda,obj32,NULL,grobfd,grcnfd,cd);              
   ...
}

그리고 위에서 CFSQP가 부르는 함수 objective인 obj32는 다음과 같습니다.

void obj32(int nparam,int j,double* x,double* fj,void* cd)
{
   *fj= pow((1. - x[0]),2.e0) + 105.e0*pow((x[1] - pow(x[0],2.e0)),2.e0);
   return;
}

결국 최종적으로 위의 obj32 함수에 pseudo_objective라는 함수가 받은 인자인 double* xreal을 x[0]에 전달하는 것이 목표입니다.
문제는 test_problem, cfsqp, 그리고 obj32 함수의 signature는 사용자가 수정 할 수 없기에(NSGA2나 CFSQP의 source를 건드리지 않는 한) 간단해 보이는 문제가 쉽지 않네요.

과연 함수에 인자 전달 없이 값을 알려주는 것이 가능한지 궁금하구요,
정 안된다면 어떤 방법으로 그나마 해결 가능한지 알고 싶습니다.
도움 부탁드립니다.

익명사용자의 이미지

그러니까 cfsqd에 넘기는 x가 obj32에서 사용하는 x하고 같은 것인가요?

만약 그렇다면, (디테일은 생략하고) x대신 xreal을 cfsqd함수에 넘기면 되지 않을까 싶은데요.....*^^*

aeronova의 이미지

그랬다면 좀 쉬워졌을텐데, 정확히는 obj32에서 사용하는 x[0](즉, x의 일부분)가 test_problem 함수에서의 xreal이랑 같습니다.

It's better to burn out than to fade away. -- Kurt Cobain.

It's better to burn out than to fade away. -- Kurt Cobain.

익명사용자의 이미지

obj32내에서 쓰이는 배열 x하고 pseudo_objective에서 cfsqp로 넘기는 x는요?

이 둘이 같다면 obj32내부에서 x[1]을 액세스할 때 문제가 생길 테니

cfsqp내에서 적어도 원소 두 개짜리 배열을 새로 만들어서 obj32로 넘기나 보네요.

이 과정이 정확하게 어떻게 일어나는지 알면 해결이 될 수도 있을 것 같은데 말이죠...

(죄송합니다. 잘 알지도 못하면서 괜히 나서서 귀찮해 드려서요... -_-;)

aeronova의 이미지

질문이 명확하지 못해서 죄송합니다.
원래 obj32가 원하는 objective입니다. x[0], x[1] 두 개의 변수를 가진 함수이지요.
근데 x[0]는 외부의 NSGA2에서 제공한 값을 받아서 사용하여 결국 x[1]만의 함수로 처리하려고 합니다.

It's better to burn out than to fade away. -- Kurt Cobain.

doldori의 이미지

cfsqp()가 콜백으로 obj32()를 호출하는 모양이군요.
그리고 pseudo_objective() 내의 x를 인자로 넘겨받는 것 같은데 그걸 이용하면 되지 않나요?

double* pseudo_objective(double* xreal)
{
    double x[2] = { *xreal, 0.1e0 };
    // ...
    cfsqp(nparam,nf,nfsr,nineqn,nineq,neqn,neq,ncsrl,ncsrn,mesh_pts,
          mode,iprint,miter,&inform,bigbnd,eps,epsneq,udelta,bl,bu,x,
          f,g,lambda,obj32,NULL,grobfd,grcnfd,cd);
    // ...
}
 
void obj32(int nparam,int j,double* x,double* fj,void* cd)
{
    // x[0] is *xreal in here
}

너무 쉽게 풀린다는 게 좀 이상하네요.
제가 잘못 이해했을 수도... ^^;

ps. pseudo_objective()에서 굳이 calloc()을 쓰지 않아도 될 듯 한데요.

ㅡ,.ㅡ;;의 이미지

그럼 함수하나사용해서 static 변수만드시죠..

void *arg_( void )
{
static void *arg1;
return arg1;
}

이런식으로해서 포인터공유시키거나.. 아니면.. 포인터를 넣게 만들어서 포인터를 넘겨주거나.. 취향대로..


----------------------------------------------------------------------------

dionysos의 이미지

void obj32(int nparam,int j,double* x,double* fj,void* cd)
함수에 보면 double로 형 인자가 double* x, double* fj 두개 있는데 이중에 하나를 이용하면 될것같네요.
두개의 인자중에 하나를 주소를 넘기고 casting 하는방식으로 하면 해결할수 있을것 같네요.

int obj32(double* fj)
{
	double *arg1,*arg2;
	arg1 = ((double*)(*((int*)fj)));
	arg2 = ((double*)(*((int*)fj + 1)));
	printf("%lf %lf\n",*arg1, *arg2);
	return 0;
}
 
 
 
int main(int argc, char* argv[])
{
	double *(d[2]);
	double *arg;
	d[0] = malloc(sizeof(double));
	d[1] = malloc(sizeof(double));
	*d[0] = 10.1;
	*d[1] = 20.1;
 
	arg = (double*)(&d[0]);
	printf("%lf %lf\n",*d[0], *d[1]);
 
	obj32(arg);
	return 0;
}

원하는 방법이 아닐수도 있지만 이렇게 하면 안되나요.

다른 방법은 생각이..ㅠㅠ..

노력은 배반하지 않는다.

노력은 배반하지 않는다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.