Hi everyone!<div><br></div><div>I have doubts about port_call and driver_init structure in a port driver.</div><div><br></div><div>This way I open the port:</div><div>Port = open_port({spawn, ?C_LIBRARY}, [binary]),</div><div>
<br></div><div>Erlang function:</div><div><div>foz(Arg)-></div><div>    call_port({1, Arg}).</div></div><div><br></div><div>C function:</div><div><div>double foz(double x) {</div><div><span class="Apple-tab-span" style="white-space:pre">    </span>return x/1.0;</div>
<div>}</div></div><div><br></div><div>I use next BIF to port calls:</div><div>erlang:port_call(Port, Command, encode(Data)),</div><div>where Command is an integer and Data is a float for example...</div><div><br></div><div>
And for encode:</div><div><div>encode(Msg)-></div><div>    term_to_binary(Msg).</div></div><div><br></div><div>This is my driver structure:</div><div><div>ErlDrvEntry driver_entry = {</div><div>    NULL,<span class="Apple-tab-span" style="white-space:pre">           </span>// called at system start up for statically</div>
<div>                // linked drivers, and after loading for</div><div>                // dynamically loaded drivers</div><div>    start,</div><div>    stop,<span class="Apple-tab-span" style="white-space:pre">         </span>// called when port is closed, and when the emulator is halted.</div>
<div>    NULL,<span class="Apple-tab-span" style="white-space:pre">             </span>//called when we have output from erlang to the port</div><div>    NULL,<span class="Apple-tab-span" style="white-space:pre">                </span>//ready_input - called when we have input from one of the driver's handles</div>
<div>    NULL,<span class="Apple-tab-span" style="white-space:pre">             </span>//ready_output - called when output is possible to one of the driver's handles</div><div>    "library",<span class="Apple-tab-span" style="white-space:pre">           </span>//driver_name - name supplied as command in open_port XXX ?</div>
<div>    NULL,<span class="Apple-tab-span" style="white-space:pre">             </span>// finish - called before unloading the driver -</div><div>                // DYNAMIC DRIVERS ONLY</div><div>    NULL,<span class="Apple-tab-span" style="white-space:pre">              </span>//handle - Reserved -- Used by emulator internally</div>
<div>    NULL,<span class="Apple-tab-span" style="white-space:pre">             </span>// control - "ioctl" for drivers - invoked by port_control/3</div><div>    NULL,<span class="Apple-tab-span" style="white-space:pre">              </span>//timeout - Handling of timeout in driver</div>
<div>    NULL,<span class="Apple-tab-span" style="white-space:pre">             </span>//outputv - called when we have output from erlang to the port</div><div>    NULL,<span class="Apple-tab-span" style="white-space:pre">              </span>// ready_async - called when the port is about to be </div>
<div>                // closed, and there is data in the </div><div>                // driver queue that needs to be flushed</div><div>                // before 'stop' can be called</div><div>    call, // call - Works mostly like 'control', a synchronous call into the driver.</div>
<div>    NULL,<span class="Apple-tab-span" style="white-space:pre">             </span>// event - Called when an event selected by driver_event() has occurred</div><div><span class="Apple-tab-span" style="white-space:pre">      </span>.extended_marker = ERL_DRV_EXTENDED_MARKER,</div>
<div><span class="Apple-tab-span" style="white-space:pre">      </span>.major_version = ERL_DRV_EXTENDED_MAJOR_VERSION,</div><div><span class="Apple-tab-span" style="white-space:pre">     </span>.minor_version = ERL_DRV_EXTENDED_MINOR_VERSION,    </div>
<div>    0,<span class="Apple-tab-span" style="white-space:pre">                </span>// ERL_DRV_FLAGs</div><div>    NULL,<span class="Apple-tab-span" style="white-space:pre">            </span>// handle2 - Reserved -- Used by emulator internally</div>
<div>    NULL,<span class="Apple-tab-span" style="white-space:pre">             </span>// process_exit - Called when a process monitor fires</div><div>    NULL,<span class="Apple-tab-span" style="white-space:pre">               </span>// stop_select - Called to close an event object</div>
<div> };</div></div><div><br></div><div>And my call function:</div><div><div>ErlDrvSSizeT call(ErlDrvData handle, unsigned int command,</div><div>char *buf, ErlDrvSizeT len,</div><div>char **rbuf, ErlDrvSizeT rlen, unsigned int *flags)</div>
<div>{</div><div><span class="Apple-tab-span" style="white-space:pre">      </span>ptr_port *ptr_port1 = (ptr_port*)handle;</div><div>    double arg, res;</div><div>    int version, index = 0;</div><div><br></div><div>    if (ei_decode_version(buf, &index, &version)) return (ErlDrvSSizeT)1;</div>
<div>    if (ei_decode_double(buf, &index, &arg)) return (ErlDrvSSizeT)2;</div><div>    </div><div>    switch (command) {</div><div>        case 1:</div><div>            res = foz(arg);</div><div>            break;</div>
<div>        case 2:</div><div>            res = baz(arg);</div><div>            break;</div><div>        default:</div><div>            return (ErlDrvSSizeT)3;</div><div>    }</div><div>    index = 0;</div><div>    if (ei_encode_version(*rbuf, &index) ||</div>
<div>    ei_encode_double(*rbuf, &index, res)) return (ErlDrvSSizeT)4;</div><div>    return (ErlDrvSSizeT)index;</div><div><br></div><div>}</div></div><div><br></div><div>My erlang version is:</div><div>Erlang R14B03 (erts-5.8.4)</div>
<div><br></div><div>My erts version doesn't have ErlDrvSizeT and ErlDrvSSizeT types, so, I include these types in my port_driver.c file:</div><div><div>typedef size_t ErlDrvSizeT;</div><div>typedef ssize_t ErlDrvSSizeT;</div>
</div><div><br></div><div>When I compile code the next warning is showed:</div><div><div>c_src/port_driver.c:78:5: warning: initialization from incompatible pointer type [enabled by default]</div><div>c_src/port_driver.c:78:5: warning: (near initialization for ‘driver_entry.flush’) [enabled by default]</div>
</div><div><br></div><div>78 line refers to call in driver_entry structure.</div><div><br></div><div>If I ignore the warning happens the next:</div><div><div>1> erl_drv:start().</div><div><0.34.0></div><div>2> erl_drv:foz(4.0).</div>
<div><br></div><div>=ERROR REPORT==== 26-Nov-2012::11:13:45 ===</div><div>Error in process <0.34.0> with exit value: {badarg,[{erlang,port_call,[erl_port,1,<<33 bytes>>]},{erl_drv,loop,1}]}</div></div><div>
<br></div><div>I couldn't change the erlang version, and I read that terms send to c call function are decoded and encoded with ei library.</div><div><br></div><div>Does anybody give me an advice?</div><div><br></div>
<div>Thank you very much.</div>