erlang 通过nif调用C 程序 (erlang调用C程序的问题)

1、

erlang调用C程序的问题,
我采用的是nif方式
代码片段:
char *y;
if (!enif_get_string(env, argv[0], y, sizeof(y), ERL_NIF_LATIN1))
我采用上面方法得到y是“123”,实际erlang传入的参数"123456"
如果我把sizeof(y) 修改成 10在erlang下会出现Segmentation fault错误提示,请问 为什么

我的提问: (不确定以下英文是否完全正确)

hi,

I using nif mehod to Invoke C funtion in Erlang.
come code:
1,
char *y;
if (!enif_get_string(env, argv[0], y,  sizeof(y), ERL_NIF_LATIN1)) 
  
I input "123456" args, but only return "123".

2,char *y;
if (!enif_get_string(env, argv[0], y,  10, ERL_NIF_LATIN1)) 

this only appear Segmentation fault

I have no idea.
Please help me. 

Thanks.
From jason.

网友的回复

"char *y" is actually just a pointer, so sizeof(y) returns 4, which is
a size of the pointer. Since you don't know how long is the string,
you should prepare a big enough buffer to receive it. So try the
following code:

#define MAXBUFLEN       1024

char y[MAXBUFLEN];
if (enif_get_string(env, argv[0], y, MAXBUFLEN, ERL_NIF_LATIN1) < 1)
   return enif_make_badarg(env);

 

> Thanks Gleb Peregud.
>
> Your are right. But a new request is come on. I input list [1,7,0,9] as
> parameter. Ii only return [1,7]. The [0,9] is lose. Maybe the '0' elment as
> a NUL in C.
> What  should i do .
>
> Thanks
>
> 8>complex6:get_name([1,7,0,9]).
> [1,7]
> 9>

Most probably enif_get_string does copy all four bytes to the buffer,
but enif_make_string treats NUL as termination mark of a string. Try
using enif_make_string_len instead.

On the other side it looks like you are interested in a binary-like
data, instead of a string-like data. You can make use of the following
code:

ErlNifBinary input;
if(!enif_inspect_iolist_as_binary(env, argv[0], &input)) {
 return enif_make_badarg(env);
}

As the result of this:
input.data - will contain pointer to a memory, where all bytes from
argument are stored
input.size - size of that memory area

Also it's worth noting that this will work for both lists (with
integers less than 256) and binaries, and for any nested combinations
of them.

hi, Gleb Peregud, Thanks to  your help. My quest is solved. 

 56     ErlNifBinary input;
 57     if(!enif_inspect_iolist_as_binary(env, argv[0], &input)) {
 58      return enif_make_badarg(env); 
 59     }
 60     char *y="yy";
 61     unsigned char* a=input.data;   
 62     int i=0;
 63     //test                                                                                                                                        
 64     while(i<input.size){
 65         fprintf(stderr,"a=%i,", a[i]);
 66         i++;
 67         //fprintf(stderr,"a=%i\n\r", *a);
 68         //a++;
 69     }
 70     fprintf(stderr,"input.size=%i\n\r", input.size);
 71     fprintf(stderr,"input.data=%s\n\r", input.data);
 72     //return enif_make_string(env, a, ERL_NIF_LATIN1);
 73     return enif_make_string_len(env, a, i,ERL_NIF_LATIN1);


Thanks agin.

from jason

 

//

  1 #include "erl_nif.h"                                                       
  2 #include "unistd.h"
  3 #include "stdio.h"
  4 #include <string.h>
  38 static ERL_NIF_TERM get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE    RM argv[])
  39 {
  56     ErlNifBinary input;
  57     if(!enif_inspect_iolist_as_binary(env, argv[0], &input)) {
  58      return enif_make_badarg(env);
  59     }
  60     char *y="yy";
  61     unsigned char* a=input.data;
  62     int i=0;
  63     //test 
  64     while(i<input.size){
  65         fprintf(stderr,"a=%i,", a[i]);
  66         i++;
  67         //fprintf(stderr,"a=%i\n\r", *a);
  68         //a++;
  69     }
  70     fprintf(stderr,"input.size=%i\n\r", input.size);                       
  71     fprintf(stderr,"input.data=%s\n\r", input.data);
  72     //return enif_make_string(env, a, ERL_NIF_LATIN1);
  73     return enif_make_string_len(env, a, i,ERL_NIF_LATIN1);
  74 //----------------------
  102 }
134 static ErlNifFunc nif_funcs[] = {
138     {"get_name", 1, get_name_nif}
140 };
141 ERL_NIF_INIT(complex6, nif_funcs, NULL, NULL, NULL, NULL)


//
%%

  1 -module(complex6).                                                         
  2 -export([foo/1, bar/1,
  3          get_name/2,
  4          get_name/1,
  5          get_list/1,
  6          test_lxw/2]).
  7 -on_load(init/0).
  8 init() ->
  9     ok = erlang:load_nif("./complex6_nif", 0).

 16 get_name(_X) ->
 17     ok.

编译
gcc -o complex6_nif.so -fpic -shared complex.c complex6_nif.c

41> c(complex6).
{ok,complex6}

43> complex6:get_name([1,0,2,0,3,4]).
a=1,a=0,a=2,a=0,a=3,a=4,input.size=6
[1,0,2,0,3,4]                                                                  44>



 

 

------------问题总算有结果了。。

官方文档:http://www.erlang.org/doc/tutorial/c_port.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值