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,
网友的回复
"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);
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.
// 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>
------------问题总算有结果了。。