简体   繁体   English

实施SWIG类型

[英]Enforce types SWIG

So I have the following C++ 所以我有以下C ++

#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;

int hello(char *str);

int hello(char *str) {
    cout << "Hello World: " << str << endl;
    return 0;
}

And the following swig interface 以及swig接口

%module sphp

%{
extern int hello(char *str);
%}

extern int hello(char *str);

And I can compile and use this in php, 我可以在php中编译和使用它,

php> hello("testing!");

This all is wicked! 这一切都是邪恶的!

Only problem is 唯一的问题是

php> hello(3);

is still valid. 仍然有效。 I don't want this, it seems swig silently casts types 我不想要这个,似乎默默无闻地投下了类型

  /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
  if ((*args[0])->type==IS_NULL) {
    arg1 = (char *) 0;
  } else {
    convert_to_string_ex(args[0]);
    arg1 = (char *) Z_STRVAL_PP(args[0]);
  }
  /*@SWIG@*/;

Now I don't want to be editing the wrapper, because its auto generated. 现在我不想编辑包装器,因为它是自动生成的。 Is there a way I can turn off this silent conversion, so that hello(3) will throw exceptions or errors, or can I give hello a hint about the type of the php argument it was originally passed? 有没有一种方法,我可以关闭此提示转换,让hello(3)将抛出异常或错误,或者我可以给hello一个关于它最初是通过PHP参数的类型暗示?

Sadly, because of how the wrapper is generated, you can't get rid of the casting completely. 可悲的是,由于包装器的生成方式,你无法完全摆脱铸件。 You can however, intercept basic datatypes and redirect them to a template function like so: 但是,您可以拦截基本数据类型并将它们重定向到模板函数,如下所示:

%module sphp

%{
  #include <iostream>

  extern int hello(char *str);

  template<class T> 
  int hello(const T &)
  {
    std::cout << "unsupported data type" << std::endl; 
  }
%}

extern int hello(char *str);

template<class T> 
int hello(const T &);

%template(hello) hello<int>;

To intercept more data types, simply add a new operator overload: 要拦截更多数据类型,只需添加一个新的运算符重载:

%template(hello) hello<double>;

Update: 更新:

Here's a more difficult approach that works by overriding SWIG's typemaps . 这是一种更难以通过覆盖SWIG的类型图来实现的方法 This is taken from SWIG's PHP typemaps and modified to prevent it from casting values. 这取自SWIG的PHP类型映射并进行了修改以防止它转换值。

%module sphp

%{
  extern int hello(char *str);
%}

%typemap(in) char *
{
  if ((*$input)->type != IS_STRING)
    SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected string");
   $1 = ($1_ltype) Z_STRVAL_PP($input);
}

%typemap(in) (char *STRING, int LENGTH), (char *STRING, size_t LENGTH) {
  if ((*$input)->type != IS_STRING)
    SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected string");
   $1 = ($1_ltype) Z_STRVAL_PP($input);
   $2 = ($2_ltype) Z_STRLEN_PP($input);
}

extern int hello(char *str);

Output: 输出:

php > include ("sphp.php");
php > hello("test");
Hello World: test
php > hello(3);
PHP Fatal error:  Type error in argument 1 of hello. Expected string in php shell code on line 1
php > hello([]);
PHP Fatal error:  Type error in argument 1 of hello. Expected string in php shell code on line 1
php > 

This is more tedious since you'll have to override every single type in the same manner if you want to get rid of automatic argument casting completely, on the other hand it gives you more control over the behaviour of argument forwarding. 这更加乏味,因为如果你想完全摆脱自动参数转换,你必须以相同的方式覆盖每一种类型,另一方面它可以让你更好地控制参数转发的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM