我正在为nodejs开发libcurl绑定,我遇到了一个小障碍。
要从卷曲处理程序调用函数curl_easy_getinfo
,我使用以下模板函数:
template<typename ResultType, typename v8MappingType>
v8::Handle<v8::Value> Curl::GetInfoTmpl( const Curl &obj, int infoId )
{
ResultType result;
CURLINFO info = (CURLINFO) infoId;
CURLcode code = curl_easy_getinfo( obj.curl, info, &result );
if ( code != CURLE_OK )
return Curl::Raise( "curl_easy_getinfo failed!", curl_easy_strerror( code ) );
return v8MappingType::New( result );
}
它的名字是这样的:
retVal = Curl::GetInfoTmpl<char*, v8::String>( *(obj), infoId );
来自libcurl文档:
CURLINFO_FTP_ENTRY_PATH
将指针传递给char指针以接收指向字符串的指针 拿着入口路径的路径。这是libcurl的初始路径 登录到远程FTP服务器时结束。 这存储了一个 如果出现问题,则为NULL指针。(在7.15.4中添加)
自7.21.4以来也适用于SFTP
好的,如果我尝试从javascript land调用getInfo(CURLINFO_FTP_ENTRY_PATH),那个空指针会使节点脚本退出,代码为-1073741819。
将空字符串作为结果放在那里的解决方法是什么?
template<typename ResultType, typename v8MappingType>
v8::Handle<v8::Value> Curl::GetInfoTmpl( const Curl &obj, int infoId )
{
ResultType result;
CURLINFO info = (CURLINFO) infoId;
CURLcode code = curl_easy_getinfo( obj.curl, info, &result );
//workaround for null pointer, aka, hack
if ( infoId == CURLINFO_FTP_ENTRY_PATH && result == NULL ) {
//what to place here to change result to an empty string?
//this section is always going to be called only when ResultType = char*
}
if ( code != CURLE_OK )
return Curl::Raise( "curl_easy_getinfo failed!", curl_easy_strerror( code ) );
return v8MappingType::New( result );
}
我刚刚开始学习C ++,所以请随意对代码做任何评论。
所以,在搜索之后,我发现了模板特化,因此为上面的函数创建了一个,但是,这基本上生成了两个具有几乎相同签名的函数,任何替代方案?
答案 0 :(得分:1)
我学习了模板专业化,并用它来解决这个问题:
template<typename ResultType, typename v8MappingType>
v8::Handle<v8::Value> Curl::GetInfoTmpl( const Curl &obj, int infoId )
{
v8::HandleScope scope;
ResultType result;
CURLINFO info = (CURLINFO) infoId;
CURLcode code = curl_easy_getinfo( obj.curl, info, &result );
if ( code != CURLE_OK )
return Curl::Raise( "curl_easy_getinfo failed!", curl_easy_strerror( code ) );
return scope.Close( v8MappingType::New( result ) );
}
template<> //template specialization
v8::Handle<v8::Value> Curl::GetInfoTmpl<char*,v8::String>( const Curl &obj, int infoId )
{
v8::HandleScope scope;
char *result;
CURLINFO info = (CURLINFO) infoId;
CURLcode code = curl_easy_getinfo( obj.curl, info, &result );
if ( !result ) { //null pointer
return scope.Close( v8::String::New( "" ) );
}
if ( code != CURLE_OK )
return Curl::Raise( "curl_easy_getinfo failed!", curl_easy_strerror( code ) );
return scope.Close( v8::String::New( result ) );
}
代码大部分是重复的,但至少问题已得到解决。如果有人有更好的解决方法,请随意发布。
上面的代码仍然不满意,我在code review上寻求帮助,@michael-urman帮助我,使用traits类的专业化,我们走了:
// traits class to determine whether to do the check
template <typename> struct ResultCanBeNull : std::false_type {};
template <> struct ResultCanBeNull<char*> : std::true_type {};
template<typename ResultType, typename v8MappingType>
v8::Handle<v8::Value> Curl::GetInfoTmpl( const Curl &obj, int infoId )
{
v8::HandleScope scope;
ResultType result;
CURLINFO info = (CURLINFO) infoId;
CURLcode code = curl_easy_getinfo( obj.curl, info, &result );
// use the traits class to filter in or out the null pointer check
if ( ResultCanBeNull<ResultType>::value && !result ) { //null pointer
return v8::String::New( "" );
}
if ( code != CURLE_OK )
return Curl::Raise( "curl_easy_getinfo failed!", curl_easy_strerror( code ) );
return scope.Close( v8MappingType::New( result ) );
}
没有重复!