2012-06-11 5 views
0

내 응용 프로그램 라이브러리는 최적화 루틴을 호출 할 필요가 :C 콜백 기능

err = optim(int n, double *x, double *f, void *obj) 

루틴은 다음 목적 함수 값을 요청하기 위해 목적 함수를 호출합니다.

void obj(int n, double *x, double *f) 

optim()는 (는) 외부 라이브러리의 일부입니다. optim() 및 obj()에 대한 서명은 고정되어 있습니다.

기능 obj()은 단일 개체 '모델'에 포함 된 데이터에 액세스해야합니다. 다른 모든 함수는 모델 객체에 대한 포인터를 전달합니다.

err = doOptimize(model) 

doOptimize()obj() 기능 액세스 변수 model에 상주 할 수있는 질문은 optim()

err= optim(model->n, model->x, model->f, model->obj) 

을 문제를 설정하고 호출합니다 : 같은 최적화 프로그램을 실행하기 위해 호출 할 수있다 오브젝트, n, xf 외에?

updateParms(model); 
    computeF(model); 

내가 obj() 실제 핸들없이이 통화를 할 수 있는지 확실하지 않다 : obj() 기능은 실제 계산을 수행 할 model 객체를 필요로 다른 함수를 호출 할 필요가? 다음과 같은 작업을 할 수 있습니까?

updateParms(); 
    computeF();  

감사합니다,

+0

'n', 'x'및 'f'회원 이외의 데이터에 대해 이야기하고 있습니까? 좀 더 정교한 코드 샘플을 제공하고 정확하게하려는 것을 나타낼 수 있습니까? –

답변

1

예,없고.

귀하의 기능 obj은 다른 메모리와 마찬가지로 모델에 액세스 할 수 있지만 주소가 model인지 알 수있는 메커니즘이 없습니다.

model 포인터를 전달할 obj에 다른 매개 변수를 추가해야합니다.

C++의 경우 objClass Model의 "구성원"으로 지정하면됩니다. 그런 다음 컴파일러는 this이라는 숨겨진 매개 변수를 추가합니다.이 매개 변수는 모든 멤버 함수에 대해 수행되며 '인스턴스'개체 인스턴스에 대한 포인터를 포함합니다. 당신이 평범한 C에서 같은 것을 달성하기 원한다면 당신은 자신의 this 포인터를 전달해야만합니다. 그러나 당신이 원하는대로 그것을 부를 수 있습니다.

그래서,이 같은 : 당신이 항상이 같은 n, xf 후 사용하는 경우 물론

... doOptimize (... model) 
{ 
    .... 
    optim (model->n, model->x, model->x, model) 
    .... 
} 

... optim (int n, double *x, double *f, ... model) 
{ 
    .... 
    model->obj (n, x, f, model); 
    .... 
} 

void obj (int n, double *x, double *f, ... model) 
{ 
    /* use n, x, and f */ 
    /* use model->stuff */ 
} 

model를 전달할 필요가 없다.

현재, 함수 포인터로 void *을 사용하지 마십시오. 좋은 생각이 아닙니다.

+0

귀하의 솔루션은 제 설명보다 문제를 잘 설명합니다. optim()은 외부 라이브러리의 일부입니다. optim() 및 obj()에 대한 서명은 고정되어 있습니다. 제가 제안한대로 문제를 공식화 할 수 없다는 사실이 문제의 동기가됩니다. – user151410

0

optim() 또는 obj()의 서명을 수정할 수 없으므로 obj() 함수에 대한 실제 호출을 수행하는 중간 단계를 만들어야합니다. 전화 한 번이 예를 들어 모델 포인터를 보유하고 정적/전역 변수처럼 간단 할 수에서 할 필요가 얼마나 많은 최적화에 따라 :

void obj(struct model *m, int n, double *x, double *f) 
{ 
    /* Access to all information here */ 
} 

static struct model *optim_model; 

void obj_caller(int n, double *x, double *f) 
{ 
    obj(optim_model, n, x, f); 
} 

int doOptimize(struct model *m) 
{ 
    optim_model = m; 
    return optim(m->n, m->x, m->f, obj_caller); 
} 

또는 당신은 고급이거나를 가진 싫어하는해야하는 경우 글로벌 단일 그리고 여러 최적화 모델을 호출 할 수 있기를 탈출하는 데 사용하는 식별자로 n 매개 변수를 사용하는 것이 가능하다 :

void obj(struct model *m, int n, double *x, double *f) 
{ 
    /* Access to all information here */ 
} 

#define MAX_MODELS (10) 
static struct model *optim_models[MAX_MODELS] = {0}; 

void obj_caller(int n, double *x, double *f) 
{ 
    for (int i = 0; i < MAX_MODELS; i++) 
    { 
     if (optim_models[i]->n == n) 
     { 
      obj(optim_models[i], n, x, f); 
      break; 
     } 
    } 
} 

int doOptimize(struct model *m) 
{ 
    return optim(m->n, m->x, m->f, obj_caller); 
} 

int main(void) 
{ 
    struct model m1; 
    struct model m2; 

    m1.n = 1; 
    optim_models[0] = &m1; 

    m2.n = 2; 
    optim_models[1] = &m1; 

    int err = doOptimize(&m2); 
} 

내가 여러 모델을 저장하기위한 더 적합한 방법을 찾을 수 coule 확신 실제 식별자가있는 연결된 목록 등 필요한 경우