2

今天是个好日子。

我需要你的 g++ 技能来了解发生在我身上的事情!

尝试链接时,g++ 告诉我:

undefined reference to `bool Script::Call<bool>(asIScriptFunction*, std::string, ...)'

而该功能在该文件中明确定义:

namespace Script
{
  template<typename RET>
  RET Call(asIScriptFunction* function, string fmt, ...)
  {
    asIScriptContext* context = Script::Engine::Get()->CreateContext();
    va_list ap;

    context->Prepare(function);
    va_start(ap, fmt);
    for (unsigned short i = 0 ; fmt[i] ; ++i)
    {
      if (i == 'O')
    context->SetArgObject(i, va_arg(ap, void*));
      else if (i == 'b')
    context->SetArgByte(i, va_arg(ap, int));
      else if (i == 'i')
    context->SetArgDWord(i, va_arg(ap, int));
      else if (i == 'f')
    context->SetArgFloat(i, va_arg(ap, double));
    }
    va_end(ap);
    context->Execute();

    RET to_ret = ScriptCallGetReturn<RET>(context);
    context->Release();
    return (to_ret);
  }
}

namespace Script
{
  template<> bool  Call<bool> (asIScriptFunction*, string fml, ...);
  template<> int   Call<int>  (asIScriptFunction*, string fml, ...);
  template<> float Call<float>(asIScriptFunction*, string fml, ...);
  template<> void* Call<void*>(asIScriptFunction*, string fml, ...);

  template<>
  void Call<void>(asIScriptFunction* function, string fmt, ...)
  {
    asIScriptContext* context = Script::Engine::Get()->CreateContext();
    va_list ap;

    context->Prepare(function);
    va_start(ap, fmt);
    for (unsigned short i = 0 ; fmt[i] ; ++i)
    {
      switch (fmt[i])
      {
    case '0':
      context->SetArgObject(i, va_arg(ap, void*));
      break ;
    case 'b':
      context->SetArgByte(i, va_arg(ap, int));
      break ;
    case 'i':
      context->SetArgDWord(i, va_arg(ap, int));
      break ;
    case 'f':
      context->SetArgFloat(i, va_arg(ap, double));
      break ;
      }
    }
    va_end(ap);
    context->Execute();
    context->Release();
  }
}

事实上,这些模板应该被编译(它们实际上在使用它们的同一个文件中)。发生这种情况的原因可能是什么?可能是因为我使用了 stdarg 吗?

4

2 回答 2

4

该函数已声明,但未在此处实现。链接器正在寻找实现。请注意,仅Call<void>在您提供的代码中实现,但Call<bool>不是。

要使您的代码正确链接,您所要做的就是删除声明:

  template<> bool  Call<bool> (asIScriptFunction*, string fml, ...);
  template<> int   Call<int>  (asIScriptFunction*, string fml, ...);
  template<> float Call<float>(asIScriptFunction*, string fml, ...);
  template<> void* Call<void*>(asIScriptFunction*, string fml, ...);
于 2012-09-29T23:29:22.350 回答
2

模板<> bool 调用 (asIScriptFunction*, string fml, ...);

这不是在做你认为它在做的事情。这是声明template <typename RET> Callwith RET<-的完整模板特化bool。你还没有定义它,旧的定义已经不存在了。函数模板特化是一种奇怪的野兽,最好避免。

我认为,您要做的是告诉编译器您将使用Call. 你不需要这样做。就用它吧。

bool variable_name = Call<bool> (some_script, other_args);
于 2012-09-29T23:54:21.763 回答