Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Programming Talk / C++ / C# - Communication between programs

Author
Message
Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 19th Jan 2011 16:30 Edited at: 19th Jan 2011 16:34
I want to be able to display a progress bar in DBP that is showing the progress of a C++ program.

My initial (and only) thought was to create a file in the C++ program and write the progress to it whilst the DBP program continually scans the file for changes.

Firstly, I'm not even sure if this is possible
Secondly, it sounds horribly inefficient!

Does anyone have any better suggestions?

Thanks

[Edit] I have another thought, although if it does work, I would't know how to implement it. Perhaps some kind of self ping. So instead of scanning a file for changes the DBP program can scan for net chat somehow(!) ... any thoughts?



IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 19th Jan 2011 19:13
Either shared memory, or a socket.

Shared memory is probably the easiest: http://msdn.microsoft.com/en-us/library/aa366551%28v=vs.85%29.aspx, and the MAP SHARED MEM TO BANK from my plug-ins.

Just write an integer into the shared memory address in your C++ program, and read it from the memory bank in DBPro.

Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 19th Jan 2011 19:28
Thanks Ian, You're a star!



Diggsey
19
Years of Service
User Offline
Joined: 24th Apr 2006
Location: On this web page.
Posted: 20th Jan 2011 02:19
Another alternative is just to send a progress message to DBPro using PostMessage() any time the progress changes. You can then set a function to be called when a message is received using IanM's commands.

[b]
Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 20th Jan 2011 13:20 Edited at: 20th Jan 2011 13:22
Cheers Diggsey.

I'm looking into the shared memory at the moment and it has brought up another idea. My DBP program is a front end for a C++ image manipulater. The c++ file creates and saves a TGA file which the DBP file then loads and displays. Both programs are running concurrently.
If I were to use shared memory, would I gain a speed advantage by not saving the image file (it only gets saved at the moment for transfer between programs) and instead send the raw image data to shared memory where the DBP file can create an image from the shared memory data?
It certainly sounds like it would be faster. Obviously the only way to know for sure is to test it but maybe someone knows of a reason why it would or wouldn't be beneficial?


Thanks



IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 20th Jan 2011 15:03
That'd work fine. Just make your C++ program write the image into the shared memory in memblock format, then use my bank commands to copy the memory to a memblock and make the image from that.

The only drawback is to make sure that you make the shared memory large enough for your largest image + any other data you want to transfer, or to dynamically create/destroy shared memory blocks on demand.

Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 20th Jan 2011 15:28
Thanks again

Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 23rd Jan 2011 14:12 Edited at: 23rd Jan 2011 14:24
I'm having problems with shared memory and I'm hoping someone could offer a hand.
My main issue is trying to decipher the MSDN 'help' site. It seems they prefer to describe things in the most obscure way and avoid plain English where-ever possible.

UnmapViewOfFile() - I can't work out what this is doing. The best I can guess is that it tells the application to 'forget' about the shared memory.

CloseHandle() - Is the similar to DBP's CLOSE FILE but for shared memory? If so, is CreateSharedMemory() the OPEN FILE equivalent?

From MSDN:
Quote: "Although an application may close the file handle used to create a file mapping object, the system holds the corresponding file open until the last view of the file is unmapped"


That statement suggests that my understanding of the above two functions is wrong and that UnmapViewOfFile() closes the file.

It seems that each application that uses shared memory needs to inform the system that it has finished with it so that the system can release it. If so, what is the DBP command for doing that? Is it IanM's DELETE BANK?

Finally, is anyone willing to take a look at my code and point out possible errors?

sharedMemory.h


sharedMemory.cpp


Filling the shared memory:

Where memStore is a sharedMemory object; mWidth, mHeight & mDepth are long integers; mAlpha is am unsigned char and mHeightMap is a std::vector<unsigned char>

The DBP access of the shared memory and conversion to image


I should point out that the above C++ code compiles without error, as does the DBP code. However, when executed the C++ file 'hangs' when asked to fill the memory and the DBP file crashes without error.

Any help greatly appreciated
Thanks

Diggsey
19
Years of Service
User Offline
Joined: 24th Apr 2006
Location: On this web page.
Posted: 23rd Jan 2011 18:35 Edited at: 23rd Jan 2011 19:24
Your putInSharedMemory function needs changing. You shouldn't unmap the file each time, and you shouldn't close the handle each time. Also, you are writing the data to the same memory location each time, so each new piece of data will overwrite the last one.

When you map a file into memory, the data is just a load of bytes one after the other. You can't keep writing to the same place and expect them to be written sequentially in the file. You have to increase the pointer by the number of bytes you write if you want to do that.

Finally, you will need some way to tell DBPro when you have finished writing to the shared memory, and a way for DBPro to tell you when it's finished reading it, and it's safe to overwrite it.

[b]
IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 23rd Jan 2011 18:39
Well, firstly, every time you write a value into your buffer, you close the map. Secondly, you are writing 4 bytes into your buffer in your putInSharedMemory function (sizeof(T) where T is a pointer) - I suggest that you pass in the value itself (possibly by reference) and get the pointer to the data within the function.

Once you've corrected that, you need to devise a protocol so that each program can tell the other when it's safe to peek or write to the shared memory - this can be as simple as having the fist integer of the shared memory being 0 if it is currently owned by the C++ program, and 1 if it is currently owned by the DBPro program.

Then you can change your C++ class to allow you to stream bytes into your buffer by keeping a 'current pointer' and moving it on when you write bytes

Finally, add two other functions - one that will check if the first 4 bytes are zero (allowing your C++ program to read/write the buffer), and another that sets it to 1 and resets your current pointer.

Re: UnmapViewOfFile
This doesn't close the file. It does however close your VIEW on the file.

The system is designed so that you can have 10's of gigabytes in a file (which obviously can't map into 2GB of address space), so you open a window or view on a portion of that file that will fit into addressable memory.

So CreateFileMapping tells windows 'I want to map this file to memory', while MapViewOfFile tells it 'I want to look at this specific portion', then 'UnmapViewOfFile' tells it 'I'm done with that portion' as a prelude to mapping another portion into memory, or closing the file mapping itself.

Quote: "If so, what is the DBP command for doing that? Is it IanM's DELETE BANK?"

Yes.

Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 10th Feb 2011 12:17 Edited at: 10th Feb 2011 13:52
I'm still having problems with this and would appreciate any further help you can offer.
I have gone back to basics and just tried to report the progress with shared memory rather than passing a full image file - that can come later when I understand it more.
Just reporting the progress means that I only need to share a single integer. So, I thought that my initial misunderstanding of writing over the first byte would be an acceptable way to do it since there is only ever one integer that needs to be written/read.

It doesn't work.

Quote: "you will need some way to tell DBPro when you have finished writing to the shared memory, and a way for DBPro to tell you when it's finished reading it, and it's safe to overwrite it."


Does this apply in this situation?
To clarify: I have a C++ file and a DBP file running concurrently. The C++ file only ever writes to shared memory and the DBP file only ever reads from it. Can they do that simultaneously?

sharedMemory.h


sharedMemory.cpp


Write to shared memory:


Reading from DBP:


Thanks

IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 11th Feb 2011 14:33
Quote: "The C++ file only ever writes to shared memory and the DBP file only ever reads from it. Can they do that simultaneously?"

Yes, but...

As long as you write data that is 1 machine word in size (ie, 4 bytes in one write), then DBPro will get complete data.

However, if your C++ program writes the next machine word before DBPro has read the previous one, it will simply be missed. This is what the coordination is all about - your C++ program signals DBPro when it is done, and waits for DBPro to signal it back before it goes on again. You can do that using a mutex or similar, or by polling for a specific value in the shared memory.

Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 11th Feb 2011 14:39 Edited at: 11th Feb 2011 14:44
Thanks,
For the current purpose of reading the progress, I don't actually care if the DBP file misses one or even several of the bytes that the C++ file is writing. It just means that my progress bar will 'jump' but that is far more acceptable than a slight slowdown by having the two programs wait for each other to be ready.
But at the moment I am obviously doing something wrong because the DBP file only ever displays a value of 0 for the progress, which I presume means it hasn't actually read anything.

Any suggestions as to where I am going wrong?

IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 11th Feb 2011 14:59
Not yet - I'll try and throw together a complete example for you when I get home later today.

IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 11th Feb 2011 22:22
This uses mostly your code with pretty much only minor adjustments, the most significant of which is passing a reference to the 'put' code so that any simple type can be passed. Run the 'sink' program first (your DBPro code), and then run the 'source' program (your C++ code).

The C++ code should also work in either Multibyte or Unicode (I only tested Unicode).

If you need it to be extended to pass more than a simple counter, let me know and I'll implement a protocol on top of the shared memory to do so.

(The download is only as large as it is because it includes the executables).

Attachments

Login to view attachments
Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 12th Feb 2011 15:21
Thanks Ian,
I don't know if I should be happy or frustrated that my code was so very nearly correct, but with your help it is now fully correct, so thank you

Quote: "If you need it to be extended to pass more than a simple counter, let me know"

Consider this me letting you know

I need to extend it to allow me to pass images from the C++ file to the DBP file. If it makes a difference, once the C++ file has placed the image in memory it will close.

Obviously, I'm going to have a crack at this myself but I very much believe I will might just need some assistance.

Thanks again.

IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 16th Feb 2011 19:33
Got anywhere, or do you want me to post my code?

Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 17th Feb 2011 10:30
I have been able to pass more than a single integer - which is a start but haven't got a full image yet.
If you've already created code for it then yes, I would very much like to have a look so I can see what I'm doing wrong.

Thanks

IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 17th Feb 2011 14:09
Ok, I'll post a complete working example for you tonight.

IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 17th Feb 2011 17:57
Code is attached.

Run the GenImage code to build a file 'image.dat'. This will be loaded by the C++ 'source' program, and passed to the DBPro 'sink' program to be displayed as a sprite.

The source program will prompt for percentage completion and pass that to the sink program. Only when you enter 100% will the source program end, and the sink program build its image.

Attachments

Login to view attachments
Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 21st Feb 2011 09:48
Thanks Ian,
I would have thanked you sooner but I have been away for the weekend for my wife's birthday.
I've had a play with it this morning and it looks like just what I need ... now to try to implement it in my code.

Thanks again!

Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 5th Mar 2011 19:38 Edited at: 5th Mar 2011 19:41
Quote: "now to try to implement it in my code."
... and FAIL!

I got the percent bit working fine, I now have a progress bar in my DBP file that accurately depicts what the C++ file is doing. But I still can't get the image sent across.

The problem I have is with putting my image data into shared memory. IanM's solution used data read from a file whereas my data is stored in a std::vector. It should be an easy conversion but I can't figure it out.
My images could be described as monochrome HDR images but in reality it is just a single float for each pixel that holds a value in the range 0.0 - 1.0
The floats are stored in a std::vector. I couldn't figure out your (IanM's) putData function but I thought I could use putValue to place everything in memory. This is what I came up with:



And to read back the data:


I have used unsigned char where DBP requires BYTES and unsigned int for DWORD - I think that is correct!?

Any chance of some more help?

Thanks

IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 5th Mar 2011 23:31 Edited at: 5th Mar 2011 23:47
One value at a time is what putValue is for. The putData is for a direct memory dump into the shared memory, so isn't useful for this.

Quote: "I have used unsigned char where DBP requires BYTES and unsigned int for DWORD - I think that is correct!?"

Yes.

I think the problem may be that you've forgotten the usage of the first 8 bytes in my example.

The first 4 bytes are for signalling progress to DBPro, and 100 means everything is done.
The next 4 bytes are used for the amount of data that has been placed within the shared memory.

After that, there's the data.

Rather than upload everything again, I'll just tell you that I removed the ampersand from the putValue member function, and here's the main source file content, that hopefully matches what you described:


Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 27th Mar 2011 22:01 Edited at: 27th Mar 2011 22:02
.. and still I fail!

As far as I can tell my code is now almost entirely the same as IanM's and yet it still doesn't work. The progress is returned OK but then when I try to pass the memblock size across it is always zero. Consequently, everything after that fails (obviously!).

This is my pass image to shared memory function:

The pusher class is the same as IanM's (see above)

My DBP file enters a repeat/until loop and displays the progress from byte 0 of shared memory until byte 0 is -99999 at which point the loop ends. byte 0 can only ever be -99999 at the end of the above function so I know it is being called. However, byte 4 which should be the size of the memblock is always 0.
I have been playing around with this for weeks but still can't figure it out.

Any suggestions?

IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 28th Mar 2011 20:05
Probably a silly question: Can you confirm that the size of your vector definitely is not zero?

Scraggle
Moderator
21
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 28th Mar 2011 20:25
Yes I can.
For debug purposes, I am displaying the image that is stored in the vector using openGL and it displays perfectly, I just can't seem to get it into DBP.

Login to post a reply

Server time is: 2025-06-25 13:45:22
Your offset time is: 2025-06-25 13:45:22