digitalmars.D.learn - std.stream.File help required (and classes)
- akaz (250/250) Mar 27 2012 Hi all,
- akaz (3/3) Mar 27 2012 I should at that the "__gshared" attribute was added in distress,
- H. S. Teoh (11/16) Mar 27 2012 [...]
- Steven Schveighoffer (11/22) Mar 27 2012 I just want to correct some inaccuracies:
- akaz (8/8) Mar 27 2012 Thank you. But why do I lose access to my std.stream.File file?
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (15/24) Mar 27 2012 std.file is more about files and directories, not file contents. I've
- akaz (80/100) Mar 27 2012 should be re-named std.folder, then, or std.filesystem. having
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (40/59) Mar 27 2012 D has this helpful syntax of treating a raw pointer as a slice. Note
- akaz (216/216) Mar 27 2012 OK, I converted into using the std.stdio.File. Without success,
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (15/33) Mar 27 2012 Judging from your free(f.data) proposal below, I think the problem is on...
- akaz (43/49) Mar 28 2012 And migrating from std.stream.File (which was a class) to
- akaz (12/17) Mar 28 2012 OMG! That solution works! Except that I was making a silly
- akaz (5/7) Mar 28 2012 Just to let you know that I did it. I was writing the good data
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (4/10) Mar 28 2012 Glad to hear it! :) I don't think there is a way of marking an NNTP
Hi all, I am trying to port some application based on a library called mediastreamer2, part of linphone software. The basic software component built on top of mediastreamer2 is called a "filter". Basically, it is a C structure with parameters and some methods (pointers to functions). Ammong the latter: a kind of constructor (.init), a kind of destructor (.uninit), some setters and a sort of "run method" (.process). The "run method" is called by an independent thread (a time ticker). It reads some queues, extract messages (packaged data) from there and process this data. Now, I implemented a filter which basically takes packaged data (messages) from an input queue and *should* write this data into a file. This is built around a std.stream.File class. Now, the questions: 1. why there is std.stdio.File, but also std.stream.File? This gives a conflict and explicit names must then be used to avoid conflict. 2. is the std.stream.File the correct choice here? Should I use std.file instead? Then, why so many file classes (count std.stdio.File too). 3. std.stream.File does not have, apparently, some easy-to-interogate properties to know the name (path) and the state of the associated file. Are there any? 4. the "run method" seems to lose knowledge about the file. The file is opened in a setter and then it should remain seekable and writeable. However, into the "run method" it appears as unseekable and unwriteable. More, trying to access .toString() property of the std.stream.File variable or to write some data into the file triggers a segmentation fault error. Here is the file msf_sinker_binaryfile.d, but if required, then I will post other files too. I am not sure how to extract a simpler test case. //========================msf_sinker_binaryfile.d========================== module msf_sinker_binaryfile; import std.stream; import std.stdio; import mediastreamer2_layer; import msf_commons; const uint MSF_SINKER_BINARYFILE_OPEN = MS_FILTER_METHOD!(byte)(cast(MSFilterId)MSFilterIdNew.MSF_SINKER_BINARYFILE_ID,0); const uint MSF_SINKER_BINARYFILE_CLOSE = MS_FILTER_METHOD_NO_ARG(cast(MSFilterId)MSFilterIdNew.MSF_SINKER_BINARYFILE_ID,1); private struct _MSF_State{ __gshared std.stream.File filedesc; //file descriptor }; private alias _MSF_State MSF_State; private void msf_init(MSFilter* f){ //a constructor printf("msf_binfile_init-start\n============================\n"); MSF_State* s=ms_new!(MSF_State)(1); s.filedesc = new std.stream.File; printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc); writef("s.filedesc.seekable=%b+++++++++++++++++++++\n",s.filedesc.seekable); writef("s.filedesc.readable=%b+++++++++++++++++++++\n",s.filedesc.readable); writef("s.filedesc.writeable=%b+++++++++++++++++++++\n",s.filedesc.writeable); writef("s.filedesc.toString=%b+++++++++++++++++++++\n",s.filedesc.toString); f.data=s; printf("msf_binfile_init-stop\n============================\n"); } private int msf_open(MSFilter* f, void* arg){ //a setter printf("msf_binfile_open-start\n============================\n"); MSF_State* s=cast(MSF_State*)f.data; ms_mutex_lock(&(f.lock)); printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc); writef("s.filedesc.seekable=%b+++++++++++++++++++++\n",s.filedesc.seekable); writef("s.filedesc.readable=%b+++++++++++++++++++++\n",s.filedesc.readable); writef("s.filedesc.writeable=%b+++++++++++++++++++++\n",s.filedesc.writeable); writef("s.filedesc.toString=%b+++++++++++++++++++++\n",s.filedesc.toString); s.filedesc.open(*(cast(string*)arg),FileMode.OutNew); printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc); writef("s.filedesc.seekable=%b+++++++++++++++++++++\n",s.filedesc.seekable); writef("s.filedesc.readable=%b+++++++++++++++++++++\n",s.filedesc.readable); writef("s.filedesc.writeable=%b+++++++++++++++++++++\n",s.filedesc.writeable); writef("s.filedesc.toString=%b+++++++++++++++++++++\n",s.filedesc.toString); ms_mutex_unlock(&(f.lock)); printf("msf_binfile_open-stop\n============================\n"); return 0; } private void msf_process(MSFilter* f){ //a run() method printf("msf_binfile_process-start\n============================\n"); MSF_State* s=cast(MSF_State*)f.data; mblk_t* m; while((m=ms_queue_get(f.inputs[0]))!=null){ //reading samples from input ms_mutex_lock(&(f.lock)); int len=cast(int)((m.b_wptr-m.b_rptr)); //length of message data block byte* p=cast(byte*)m.b_rptr; /*printf("----------------------------\n"); for(int idx=0; idx<len; idx++){ printf("d_data[%d]=%d\n",idx,d_data[idx]); } printf("----------------------------\n");*/ //File filedesc; //filedesc.open("newfile.bin","w+b"); printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc); writef("s.filedesc.seekable=%b+++++++++++++++++++++\n",s.filedesc.seekable); writef("s.filedesc.readable=%b+++++++++++++++++++++\n",s.filedesc.readable); writef("s.filedesc.writeable=%b+++++++++++++++++++++\n",s.filedesc.writeable); writef("s.filedesc.toString=%b+++++++++++++++++++++\n",s.filedesc.toString); //s.filedesc.writeString("This writes a string to the file. "); //s.filedesc.writeBlock(p,len); //filedesc.close(); ms_mutex_unlock(&(f.lock)); freemsg(m); } printf("msf_binfile_process-start\n============================\n"); } private int msf_close(MSFilter* f, void* arg){ //an unsetter MSF_State* s=cast(MSF_State*)f.data; ms_mutex_lock(&(f.lock)); s.filedesc.close(); ms_mutex_unlock(&(f.lock)); return 0; } private void msf_uninit(MSFilter* f){ //a destructor MSF_State* s=cast(MSF_State*)f.data; msf_close(f, null); ms_free(s); } private immutable MSFilterMethod[3] msf_methods=[ {id:MSF_SINKER_BINARYFILE_OPEN,method:cast(MSFilterMethodFunc)&msf_open}, {id:MSF_SINKER_BINARYFILE_CLOSE,method:cast(MSFilterMethodFunc)&msf_close}, {0,null} ]; immutable MSFilterDesc msf_sinker_binaryfile_desc={ id:cast(MSFilterId)MSFilterIdNew.MSF_SINKER_BINARYFILE_ID, name:"MSFileSink", text:"File sink", category:MSFilterCategory.MS_FILTER_OTHER, ninputs:1, noutputs:0, init:cast(MSFilterFunc)&msf_init, process:cast(MSFilterFunc)&msf_process, uninit:cast(MSFilterFunc)&msf_uninit, methods:cast(MSFilterMethod*)&msf_methods[0] }; //======================================================================== The segmentation fault appears on line 68 (the line "writef("s.filedesc.toString=%b+++++++++++++++++++++\n",s.filedesc.toString);" inside the msf_process() function (there are several lines like that - debug messages). The output of the software is: warning: GDB: Failed to set controlling terminal: Operation not permitted -------START PROGRAM------- ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 0 ALSA lib control.c:951:(snd_ctl_open_noupdate) Invalid CTL default:0 ortp-warning-Could not attach mixer to card: Invalid argument ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 0 ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:0 ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 0 ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:0 ortp-warning-Strange, sound card HDA Intel does not seems to be capable of anything, retrying with plughw... ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 1 ALSA lib control.c:951:(snd_ctl_open_noupdate) Invalid CTL default:1 ortp-warning-Could not attach mixer to card: Invalid argument ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 1 ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:1 ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 1 ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:1 ortp-warning-Strange, sound card HDA ATI HDMI does not seems to be capable of anything, retrying with plughw... ortp-warning-Strange, sound card HDA ATI HDMI seems totally unusable. msf_binfile_init-start ============================ s.filedesc=0x7ffff7ebcf40+++++++++++++++++++++ s.filedesc.seekable=0+++++++++++++++++++++ s.filedesc.readable=0+++++++++++++++++++++ s.filedesc.writeable=0+++++++++++++++++++++ s.filedesc.toString=[1110011, 1110100, 1100100, 101110, 1110011, 1110100, 1110010, 1100101, 1100001, 1101101, 101110, 1000110, 1101001, 1101100, 1100101]+++++++++++++++++++++ msf_binfile_init-stop ============================ msf_set_freq-start ============================ msf_set_freq-stop ============================ msf_set_rate-start ============================ msf_set_rate-stop ============================ msf_binfile_open-start ============================ s.filedesc=0x7ffff7ebcf40+++++++++++++++++++++ s.filedesc.seekable=0+++++++++++++++++++++ s.filedesc.readable=0+++++++++++++++++++++ s.filedesc.writeable=0+++++++++++++++++++++ s.filedesc.toString=[1110011, 1110100, 1100100, 101110, 1110011, 1110100, 1110010, 1100101, 1100001, 1101101, 101110, 1000110, 1101001, 1101100, 1100101]+++++++++++++++++++++ s.filedesc=0x7ffff7ebcf40+++++++++++++++++++++ s.filedesc.seekable=1+++++++++++++++++++++ s.filedesc.readable=0+++++++++++++++++++++ s.filedesc.writeable=1+++++++++++++++++++++ s.filedesc.toString=[1110011, 1110100, 1100100, 101110, 1110011, 1110100, 1110010, 1100101, 1100001, 1101101, 101110, 1000110, 1101001, 1101100, 1100101]+++++++++++++++++++++ msf_binfile_open-stop ============================ msf_sinusoid_process-start ============================ s.rate=4000.000000============================ msf_sinusoid_process-stop ============================ msf_split_process-start ============================ msf_split_process-stop ============================ msf_dbl2int16_process-start ============================ msf_dbl2int16_process-stop ============================ ortp-warning-alsa_set_params: periodsize:0 Using 64 ortp-warning-alsa_set_params: period:8 Using 8 msf_binfile_process-start ============================ s.filedesc=0x7ffff7ebcf40+++++++++++++++++++++ s.filedesc.seekable=0+++++++++++++++++++++ s.filedesc.readable=0+++++++++++++++++++++ s.filedesc.writeable=0+++++++++++++++++++++ Segmentation fault (core dumped) Strangely, the file is writeable and seekable in the msf_open() function, but it becomes unseekable and unwriteable in the msf_process() function. Do I lose my file descriptor when exiting the msf_open() function? If yes, how to keep it? It is because of the TLS variables? Thank you.
Mar 27 2012
I should at that the "__gshared" attribute was added in distress, but changed nothing. With or without it, the program still crashes.
Mar 27 2012
On Tue, Mar 27, 2012 at 01:58:03PM +0200, akaz wrote: [...]Now, the questions: 1. why there is std.stdio.File, but also std.stream.File? This gives a conflict and explicit names must then be used to avoid conflict.[...] This is a design flaw that will be fixed eventually. There's a std.io module in the works that will eventually replace std.stream and std.stdio. Unfortunately it's at a roadblock right now. For the conflicts, you could try using 'alias' to disambiguate between them, or any of the various import aliasing tools. T -- The early bird gets the worm. Moral: ewww...
Mar 27 2012
On Tue, 27 Mar 2012 10:46:08 -0400, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:On Tue, Mar 27, 2012 at 01:58:03PM +0200, akaz wrote: [...]I just want to correct some inaccuracies: 1. std.io will *not* replace std.stdio, it will replace std.stream. std.stdio.File will be able to use std.io's objects as implementation, but this will be transparent to existing code. 2. There is not a roadblock, I'm working on it very slowly is all :) I'm hoping to have something more concrete soon. I just got RefCounted to work with classes, and that was a major issue, since std.io is interface/class based. -SteveNow, the questions: 1. why there is std.stdio.File, but also std.stream.File? This gives a conflict and explicit names must then be used to avoid conflict.[...] This is a design flaw that will be fixed eventually. There's a std.io module in the works that will eventually replace std.stream and std.stdio. Unfortunately it's at a roadblock right now.
Mar 27 2012
Thank you. But why do I lose access to my std.stream.File file? Somehow, the variable gets unallocated, thus the file is closed back? With pointers of C it used to be so simple... variable remained allocated untel the corresponding free(). I do not quite grasp this (a bit) awkward mix between pointers and classes (references?). Sometimes is like C/C++, sometimes is like Java...
Mar 27 2012
On 03/27/2012 04:58 AM, akaz wrote:2. is the std.stream.File the correct choice here? Should I use std.file instead? Then, why so many file classes (count std.stdio.File too).std.file is more about files and directories, not file contents. I've abandoned std.stream.File some time ago. I just use std.stdio.File partly because stdio, stdout, and stderr are of that type anyway. It works with ranges as well.3. std.stream.File does not have, apparently, some easy-to-interogate properties to know the name (path) and the state of the associated file.std.stdio.File provides name() for the name and getFP() if you want to access the underlying FILE*.private void msf_init(MSFilter* f){ //a constructor printf("msf_binfile_init-start\n============================\n"); MSF_State* s=ms_new!(MSF_State)(1); s.filedesc = new std.stream.File;[...]f.data=s;We are assuming that f never goes away and that f.data is not assigned anything else, right? Otherwise the garbage collector will destroy that MSF_State and reclaim its memory at an indeterminate time. Is it possible that you use the MSF_State object longer than you should, after it's lifetime ended? If you did, the object would look usable for a while until the GC collects it. Ali
Mar 27 2012
std.file is more about files and directories, not file contents. I've abandoned std.stream.File some time ago. I just use std.stdio.File partly because stdio, stdout, and stderr are of that type anyway. It works with ranges as well.should be re-named std.folder, then, or std.filesystem. having another "file" there is quite confusing. Oh, no! there is also a... std.cstream!std.stdio.File provides name() for the name and getFP() if you want to access the underlying FILE*.I understand that std.stdio.File is the newer approach. OK, I will try to use that instead. BUT: what is the equivalent of std.stream.File.writeBlock(const void* buffer, size_t size)? I see there is a std.stdio.rawWrite(T)(in T[] buffer); But, my data is: a (byte*) pointer and a length. How do I write something like std.stream.File.writeblock(cast(byte*)p,cast(int)len) using std.stdio.File.rawWrite? And why std.stream.File is not marked as deprecated if a better (newer) alternative exists?Yes, that should be the case. f is the mother structure (a pointer towards a MSFilter structure) that should never disappear and f.data should not be assigned somewhere else. I have several other "filters" implemented using the same schema and they seem to work quite well, except that they do not use files or... classes (I still cannot grasp that fundamental thing when a class instance is a variable and when it is a pointer; when is T x; and when is T* x = new T(); or, when is T* x=(T*)calloc(1,sizeof(T));) For the record, here is the "main.d" filter: =========================main.d=========================== import std.stdio; import core.thread; import std.math; import mediastreamer2_layer; import msf_sourcer_sinusoid; import msf_converter_double2int16_t; import msf_sinker_binaryfile; import msf_processor_split; import msf_sinker_void; int main(char[][] args) { MSTicker* ticker; MSFilter* src_sinus; MSFilter* cnv_dbl2int16_t; MSFilter* snk_sndcrd; MSFilter* snk_binfile; MSFilter* prc_split1; MSFilter* prc_split2; MSFilter* snk_void; printf("-------START PROGRAM-------\n"); ms_init(); src_sinus=ms_filter_new_from_desc(&msf_sourcer_sinusoid_desc); cnv_dbl2int16_t=ms_filter_new_from_desc(&msf_converter_double2int16_t_desc); snk_sndcrd=ms_snd_card_create_writer(ms_snd_card_manager_get_default_card(ms_snd_card_manager_get())); snk_binfile=ms_filter_new_from_desc(&msf_sinker_binaryfile_desc); prc_split1=ms_filter_new_from_desc(&msf_processor_split_desc); prc_split2=ms_filter_new_from_desc(&msf_processor_split_desc); snk_void=ms_filter_new_from_desc(&msf_sinker_void_desc); double f0=1000.0; ms_filter_call_method(src_sinus,MSF_SOURCER_SINUSOID_SET_FREQ,&f0); double fe=4000.0; ms_filter_call_method(src_sinus,MSF_SOURCER_SINUSOID_SET_RATE,&fe); int fe_int=cast(int)round(fe); ms_filter_call_method(snk_sndcrd,MS_FILTER_SET_SAMPLE_RATE,&fe_int); string numefisier="file_givenname.bin"; ms_filter_call_method(snk_binfile,MSF_SINKER_BINARYFILE_OPEN,cast(void*)&numefisier); ms_filter_link(src_sinus,0,prc_split1,0); ms_filter_link(prc_split1,0,cnv_dbl2int16_t,0); ms_filter_link(prc_split1,1,snk_binfile,0); ms_filter_link(cnv_dbl2int16_t,0,snk_sndcrd,0); ticker=ms_ticker_new(); ms_ticker_attach(ticker,src_sinus); //START Thread.sleep(dur!("seconds")(3)); ms_ticker_detach(ticker,src_sinus); //STOP ms_ticker_destroy(ticker); ms_filter_call_method_noarg(snk_binfile,MSF_SINKER_BINARYFILE_CLOSE); ms_exit(); printf("-------STOP PROGRAM-------\n"); return 0; } ============================================================== Finally: thank you very much for your help! I expected D to be a sort of "better C with *facultative* classes" but I find it to beprivate void msf_init(MSFilter* f){ //a constructorprintf("msf_binfile_init-start\n============================\n");MSF_State* s=ms_new!(MSF_State)(1); s.filedesc = new std.stream.File;[...]f.data=s;We are assuming that f never goes away and that f.data is not assigned anything else, right? Otherwise the garbage collector will destroy that MSF_State and reclaim its memory at an indeterminate time. Is it possible that you use the MSF_State object longer than you should, after it's lifetime ended? If you did, the object would look usable for a while until the GC collects it.
Mar 27 2012
On 03/27/2012 02:20 PM, akaz wrote:what is the equivalent of std.stream.File.writeBlock(const void* buffer, size_t size)? I see there is a std.stdio.rawWrite(T)(in T[] buffer); But, my data is: a (byte*) pointer and a length. How do I write something like std.stream.File.writeblock(cast(byte*)p,cast(int)len) using std.stdio.File.rawWrite?D has this helpful syntax of treating a raw pointer as a slice. Note p[0..length] below: import std.stdio; void main() { byte[] bytes = [ 81, 82, 83, 84, 85 ]; byte * p = &(bytes[1]); size_t length = 3; auto file = File("raw_written_bytes", "w"); file.rawWrite(p[0..length]); }Yes, that should be the case. f is the mother structure (a pointer towards a MSFilter structure) that should never disappear and f.data should not be assigned somewhere else.How is all that memory allocated?I still cannot grasp that fundamental thing when a class instance is a variable and when it is a pointerIf you don't mind, your code has way too many pointers. :) As a person coming from C++, here is how I made sense of it: auto var = new MyClass(); The line above has two entities: 1) An anonymous MyClass object on the right-hand side which belongs to the runtime. It will be garbage collected later. 2) The 'class variable' on the left-hand side. This is the handle to that object. You can think of this as being implemented as a pointer behind the scene, but there is no pointer in D with classes. To complicate matters, you can spell out the type of 'var': MyClass var = new MyClass(); Very confusing, but the actual types of the left-hand and right-hand sides are still different: "class variable" vs. "class object".; when is T x;Prefer that one until it doesn't compile. :)and when is T* x = new T();That is needed when T is a value type (e.g. a struct) and that you want to handle its lifetime manually.or, when is T* x=(T*)calloc(1,sizeof(T));)Since calloc() is a C library function, you must use a T* there. Speaking of which, is f.data in such a memory that GC is not aware of? Then your class reference in there will not keep the File object alive. You must call GC.addRange() to let GC know that you have pointers into the GC's memory. A better thing to do may be to call GC.calloc() from the core.memory module. (Hmmm. Maybe I will translate this chapter next: http://ddili.org/ders/d/bellek_yonetimi.html )I expected D to be a sort of Is my vision correct?from many languages. :) Ali
Mar 27 2012
OK, I converted into using the std.stdio.File. Without success, the programs till crashes. However, in the meantime: A) why there is no parameter-less constructor for std.stdio.File? I would like to have into my "init" function: s.filedesc=new File() and, then, in my setter "open" method s.filedesc.open(name,mode). Because I have no such constructor, I am forced to have in the "init": s.filedesc=null; and in the "open": s.filedesc=new File(name,mode). However, in that case, what use for the std.stdio.File.open method? If the name and the mode *must* be known at the construction time, then why ask those once more for the std.stdio.File.open() method? I am forced to open, first, a dummy file (in the constructor), only to be able to call, later, the std.stdio.File.open() method with the correct file name? B) In my function: private int msf_open(MSFilter* f, void* arg){ //a setter printf("msf_binfile_open-start\n============================\n"); MSF_State* s=cast(MSF_State*)f.data; ms_mutex_lock(&(f.lock)); s.filedesc = new File(*(cast(string*)arg),"w+b"); printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc); writef("s.filedesc.isOpen=%b+++++++++++++++++++++\n",s.filedesc.isOpen); writef("s.filedesc.name=%s+++++++++++++++++++++\n",s.filedesc.name); writef("s.filedesc.size=%d+++++++++++++++++++++\n",s.filedesc.size); ms_mutex_unlock(&(f.lock)); printf("msf_binfile_open-stop\n============================\n"); return 0; } can you tell me if the line s.filedesc=new File(*(cast(string*)arg),"w+b"); PROPAGATES the change into f.data? (recall that MSF_State* s=cast(MSF_State*)f.data;). I should also force, at the end of the function (just before return), something like: free(f.data); f.data=s; to propagate this? As dumb as it may seem: is my "s" variable in MSF_State* s=cast(MSF_State*)f.data; a POINTER or a VALUE? I should write s->filedesc? Or, maybe, (*s).filedesc? I am a bit lost between pointers (s->x or (*s).x) and values (s.x). For structures there are pointers, for classes there are no pointers? Finally, the program crash on the same line, when trying to write something in the file. Irony is that the s.filedesc.isOpen shows... 1. Here is my new "msf_sinker_binaryfile.d file: =======================msf_sinker_binaryfile.d====================== module msf_sinker_binaryfile; import std.stdio; import mediastreamer2_layer; import msf_commons; const uint MSF_SINKER_BINARYFILE_OPEN = MS_FILTER_METHOD!(byte)(cast(MSFilterId)MSFilterIdNew.MSF_SINKER_BINARYFILE_ID,0); const uint MSF_SINKER_BINARYFILE_CLOSE = MS_FILTER_METHOD_NO_ARG(cast(MSFilterId)MSFilterIdNew.MSF_SINKER_BINARYFILE_ID,1); private struct _MSF_State{ File* filedesc; //file descriptor }; private alias _MSF_State MSF_State; private void msf_init(MSFilter* f){ //a constructor printf("msf_binfile_init-start\n============================\n"); MSF_State* s=ms_new!(MSF_State)(1); s.filedesc = null; f.data=s; printf("msf_binfile_init-stop\n============================\n"); } private int msf_open(MSFilter* f, void* arg){ //a setter printf("msf_binfile_open-start\n============================\n"); MSF_State* s=cast(MSF_State*)f.data; ms_mutex_lock(&(f.lock)); s.filedesc = new File(*(cast(string*)arg),"w+b"); printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc); writef("s.filedesc.isOpen=%b+++++++++++++++++++++\n",s.filedesc.isOpen); writef("s.filedesc.name=%s+++++++++++++++++++++\n",s.filedesc.name); writef("s.filedesc.size=%d+++++++++++++++++++++\n",s.filedesc.size); ms_mutex_unlock(&(f.lock)); printf("msf_binfile_open-stop\n============================\n"); return 0; } private void msf_process(MSFilter* f){ //a run() method printf("msf_binfile_process-start\n============================\n"); MSF_State* s=cast(MSF_State*)f.data; mblk_t* m; while((m=ms_queue_get(f.inputs[0]))!=null){ //reading samples from input ms_mutex_lock(&(f.lock)); int len=cast(int)((m.b_wptr-m.b_rptr)); //length of message data block byte* p=cast(byte*)m.b_rptr; /*printf("----------------------------\n"); for(int idx=0; idx<len; idx++){ printf("d_data[%d]=%d\n",idx,d_data[idx]); } printf("----------------------------\n");*/ //File filedesc; //filedesc.open("newfile.bin","w+b"); printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc); writef("s.filedesc.isOpen=%b+++++++++++++++++++++\n",s.filedesc.isOpen); //writef("s.filedesc.name=%s+++++++++++++++++++++\n",s.filedesc.name); //SEGFAULT //writef("s.filedesc.size=%d+++++++++++++++++++++\n",s.filedesc.size); //SEGFAULT s.filedesc.writefln("This writes a string to the file."); //SEGFAULT //s.filedesc.writeBlock(p,len); //filedesc.close(); ms_mutex_unlock(&(f.lock)); freemsg(m); } printf("msf_binfile_process-start\n============================\n"); } private int msf_close(MSFilter* f, void* arg){ //an unsetter MSF_State* s=cast(MSF_State*)f.data; ms_mutex_lock(&(f.lock)); s.filedesc.close(); ms_mutex_unlock(&(f.lock)); return 0; } private void msf_uninit(MSFilter* f){ //a destructor MSF_State* s=cast(MSF_State*)f.data; msf_close(f, null); ms_free(s); } private immutable MSFilterMethod[3] msf_methods=[ {id:MSF_SINKER_BINARYFILE_OPEN,method:cast(MSFilterMethodFunc)&msf_open}, {id:MSF_SINKER_BINARYFILE_CLOSE,method:cast(MSFilterMethodFunc)&msf_close}, {0,null} ]; immutable MSFilterDesc msf_sinker_binaryfile_desc={ id:cast(MSFilterId)MSFilterIdNew.MSF_SINKER_BINARYFILE_ID, name:"MSFileSink", text:"File sink", category:MSFilterCategory.MS_FILTER_OTHER, ninputs:1, noutputs:0, init:cast(MSFilterFunc)&msf_init, process:cast(MSFilterFunc)&msf_process, uninit:cast(MSFilterFunc)&msf_uninit, methods:cast(MSFilterMethod*)&msf_methods[0] }; ============================================================== and here is the output of the program: -------START PROGRAM------- ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 0 ALSA lib control.c:951:(snd_ctl_open_noupdate) Invalid CTL default:0 ortp-warning-Could not attach mixer to card: Invalid argument ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 0 ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:0 ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 0 ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:0 ortp-warning-Strange, sound card HDA Intel does not seems to be capable of anything, retrying with plughw... ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 1 ALSA lib control.c:951:(snd_ctl_open_noupdate) Invalid CTL default:1 ortp-warning-Could not attach mixer to card: Invalid argument ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 1 ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:1 ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 1 ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:1 ortp-warning-Strange, sound card HDA ATI HDMI does not seems to be capable of anything, retrying with plughw... ortp-warning-Strange, sound card HDA ATI HDMI seems totally unusable. msf_binfile_init-start ============================ msf_binfile_init-stop ============================ msf_set_freq-start ============================ msf_set_freq-stop ============================ msf_set_rate-start ============================ msf_set_rate-stop ============================ msf_binfile_open-start ============================ s.filedesc=0x7ff83baacff0+++++++++++++++++++++ s.filedesc.isOpen=1+++++++++++++++++++++ s.filedesc.name=file_givenname.bin+++++++++++++++++++++ s.filedesc.size=0+++++++++++++++++++++ msf_binfile_open-stop ============================ msf_sinusoid_process-start ============================ s.rate=4000.000000============================ msf_sinusoid_process-stop ============================ msf_split_process-start ============================ msf_split_process-stop ============================ msf_dbl2int16_process-start ============================ msf_dbl2int16_process-stop ============================ ortp-warning-alsa_set_params: periodsize:0 Using 64 ortp-warning-alsa_set_params: period:8 Using 8 msf_binfile_process-start ============================ s.filedesc=0x7ff83baacff0+++++++++++++++++++++ s.filedesc.isOpen=1+++++++++++++++++++++ Segmentation fault (core dumped) Any help?
Mar 27 2012
On 03/27/2012 02:57 PM, akaz wrote:B) In my function: private int msf_open(MSFilter* f, void* arg){ //a setter printf("msf_binfile_open-start\n============================\n"); MSF_State* s=cast(MSF_State*)f.data; ms_mutex_lock(&(f.lock)); s.filedesc = new File(*(cast(string*)arg),"w+b");Judging from your free(f.data) proposal below, I think the problem is on the previous line: the object is allocated in GC's memory but s.filedesc is in a memory that GC is not scanning. You must call GC.addRange() when you allocate the memory that s.filedesc is living on.can you tell me if the line s.filedesc=new File(*(cast(string*)arg),"w+b"); PROPAGATES the change into f.data?Yes. It is the same as in C.(recall that MSF_State* s=cast(MSF_State*)f.data;). I should also force, at the end of the function (just before return), something like: free(f.data); f.data=s; to propagate this?Not to propagate, but you may have to call free() to avoid a leak.As dumb as it may seem: is my "s" variable in MSF_State* s=cast(MSF_State*)f.data; a POINTER or a VALUE?A pointer just like in C.I should write s->filedesc? Or, maybe, (*s).filedesc?That syntax has been useless even in C. (Although it communicates something to the reader.) The compiler could use the dot operator and do the right thing depending on whether the left-hand side was a pointer or an object. D does not have the -> operator.I am a bit lost between pointers (s->x or (*s).x) and values (s.x). For structures there are pointers, for classes there are no pointers?Yes. Ali
Mar 27 2012
And migrating from std.stream.File (which was a class) to std.stdio.File (which is a structure) lost me completely. Why, in fact, std.stream.File is a structure and not a class? Citing: http://dlang.org/phobos/std_stdio.html struct File; Encapsulates a FILE*. Generally D does not attempt to provide thin wrappers over equivalent functions in the C standard library, but manipulating FILE* values directly is unsafe and error-prone in many ways. The File type ensures safe manipulation, automatic file closing, and a lot of convenience. The underlying FILE* handle is maintained in a reference-counted manner, such that as soon as the last File variable bound to a given FILE* goes out of scope, the underlying FILE* is automatically closed. May I disable that reference counting? I do not get how to use GC.addRange(). Can you, please, direct me towards an example? You seem to be right, the f and f.data variables are allocated into my C code, so they are invisible to the garbage collector. BUT!!! Is there any way to disable that garbage collector straight from the beginning? Maybe a compiler flag? I should also add that I allocated my structure with: (init) s.filedesc = cast(File*)GC.calloc(1,File.sizeof); (open) (*(s.filedesc)).open(*(cast(string*)arg),"w+b"); but without success, since the MSF_State* s=ms_new!(MSF_State)(1); line allocating the memory for s is esentially a C library function (a wrapper around it): extern(C){ //... void* ortp_malloc(size_t sz); T* ortp_new(T)(int count){ return cast(T*)ortp_malloc(T.sizeof*count); } alias ortp_new ms_new; //... } so that allocation is not visible to the garbage collector. My code has so many pointers because I took it from C, directly. Many of those pointers are also imposed by the underlying (C) library. I had no intention to extensively re-write my code, just to port it.I am a bit lost between pointers (s->x or (*s).x) and values (s.x). For structures there arepointers,for classes there are no pointers?Yes. Ali
Mar 28 2012
I should also add that I allocated my structure with: (init) s.filedesc = cast(File*)GC.calloc(1,File.sizeof); (open) (*(s.filedesc)).open(*(cast(string*)arg),"w+b");OMG! That solution works! Except that I was making a silly mistake and thought that GC.alloc() prototype is similar to C's calloc (since it has two parameters). I fact, after writing: (init) s.filedesc = cast(File*)GC.calloc(File.sizeof*1); (open) (*(s.filedesc)).open(*(cast(string*)arg),"w+b"); now, my file remains open and I can write inside! (The data inside is not really what it should be, but that, at least, is a debugging problem, not a segfault one). Thank you once again!
Mar 28 2012
(The data inside is not really what it should be, but that, at least, is a debugging problem, not a segfault one).Just to let you know that I did it. I was writing the good data (as double), but it was my verification test that assumed it to be int... Now I corrected it and it works! Any way to mark this thread as solved?
Mar 28 2012
On 03/28/2012 05:09 AM, akaz wrote:Glad to hear it! :) I don't think there is a way of marking an NNTP thread as solved. Ali(The data inside is not really what it should be, but that, at least, is a debugging problem, not a segfault one).Just to let you know that I did it. I was writing the good data (as double), but it was my verification test that assumed it to be int... Now I corrected it and it works! Any way to mark this thread as solved?
Mar 28 2012