首页  »   编程

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

网友分享于:2013-10-31  浏览:71次
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

相关解决方案

最新解决方案