Jump to content


passing an array pointer between two processes?


20 replies to this topic

#1 celu

    New Member

  • Members
  • PipPip
  • 20 posts

Posted 23 February 2007 - 07:15 AM

Hi guys, I have this maya plugin which creates an array on heap.Now I want to read this array from my directX application.Basically for passing some real time data between the plugin and my DirectX application.My plugin writes to the array and my Directx application only reads those values.How do I acheive this? Im basically new to Inter Process Communication.Any suggestions as to what I need to look into would be really helpful.Im using win32 and VS 2005 IDE..if that helps...Thx.

#2 Kenneth Gorking

    Senior Member

  • Members
  • PipPipPipPip
  • 907 posts

Posted 23 February 2007 - 09:47 AM

Either memory mapping or named pipes should do the trick.
"Stupid bug! You go squish now!!" - Homer Simpson

#3 dave_

    Senior Member

  • Members
  • PipPipPipPip
  • 584 posts

Posted 23 February 2007 - 10:15 AM

There are loads of ways of doing it


Personally I like sockets because it can then be extended across networks too.
But it sounds like you want shared memory. Named pipes seems like a good approach to this.

#4 celu

    New Member

  • Members
  • PipPip
  • 20 posts

Posted 23 February 2007 - 05:46 PM

thx a lot..ill look into them..will get back if i need further clarifications...thx :)

#5 lstockman

    New Member

  • Members
  • Pip
  • 7 posts

Posted 23 February 2007 - 07:11 PM

dave_ said:

There are loads of ways of doing it


Personally I like sockets because it can then be extended across networks too.
But it sounds like you want shared memory. Named pipes seems like a good approach to this.

Just by chance, how would you pass an array using sockets? I'm not that great at network programming and this is one of my challenges that I look forward to tackeling so that I can increase my skill. Any help would be appreciated.

#6 Reedbeta

    DevMaster Staff

  • Administrators
  • 4782 posts
  • LocationBellevue, WA

Posted 23 February 2007 - 10:18 PM

If it's a TCP socket, you just write the array data to the socket in order, and read it back on the other end. Of course if the data contains pointers you have to change them to indices or else they won't make sense (since they won't have the same addresses on the destination side).
reedbeta.com - developer blog, OpenGL demos, and other projects

#7 celu

    New Member

  • Members
  • PipPip
  • 20 posts

Posted 24 February 2007 - 02:55 AM

but passing a pointer to an array (allocated on the heap) between two processes on the same machine wont be a problem rite? unlike in a network...the pointer will still point to the same array on the receiving process also init?

#8 Nils Pipenbrinck

    Senior Member

  • Members
  • PipPipPipPip
  • 597 posts

Posted 24 February 2007 - 03:49 AM

On Win32 there is an api for that. Lookup GlobalAlloc. It will allocate memory and give you a handle. You can lock and unlock the handle to get a pointer to work with.

The idea behind this is that it's valid to pass the handle between processes. The kernel then maps the memory into the process address space. All processes that work with that handle will see the same physical memory.

#9 Reedbeta

    DevMaster Staff

  • Administrators
  • 4782 posts
  • LocationBellevue, WA

Posted 24 February 2007 - 04:46 AM

celu said:

but passing a pointer to an array (allocated on the heap) between two processes on the same machine wont be a problem rite? unlike in a network...the pointer will still point to the same array on the receiving process also init?

No, because each process executes in its own virtual address space. Processes don't normally have access to each others' memory. However you can use GlobalAlloc as Nils suggested, or you can also use the memory-mapped I/O API, which does more or less the same thing.
reedbeta.com - developer blog, OpenGL demos, and other projects

#10 celu

    New Member

  • Members
  • PipPip
  • 20 posts

Posted 24 February 2007 - 07:21 PM

I allocated a memory block using the GlobalAlloc() function and obtained a handle to that block.I filled the block with my array data by locking the handle.Then I passed the memory block handle to my second process using a named pipe.Now I have the memory handle in my second process,It still points to the same address as in the first process(I verified this using the debugger).But when i try to lock the handle it returns a null pointer.Im not able get a pointer to my array data that I loaded in the first process.What could be going wrong? I cant seem to find the reason...my initial hunch was that it had something to do with the allocation flag of my GlobalAlloc() function i tried changing the allocation flag from GMEM_FIXED to GMEM_MOVEABLE.But that made no difference.

#11 Reedbeta

    DevMaster Staff

  • Administrators
  • 4782 posts
  • LocationBellevue, WA

Posted 24 February 2007 - 08:32 PM

If you already have a named pipe, why not just send the data through that?
reedbeta.com - developer blog, OpenGL demos, and other projects

#12 Nils Pipenbrinck

    Senior Member

  • Members
  • PipPipPipPip
  • 597 posts

Posted 24 February 2007 - 10:13 PM

Celu,

You almost got it. Global Memory handles are serialized. Only one process can lock it. So after process A has written some stuff it has to unlock the handle. Then process B can lock it and read/write the data.

You might see the same pointer in all processes. If so the kernel has allocated shared address-space for you (ain't that nice?). You can't however access the data without locking. Just locking once and remembering the pointer won't work.

If you have a pipe and you can send data, use it. I personally find global memory handles easier to deal with (I pass them around using window-messages or across dll boundaries). It's just a mater of preference though.
My music: http://myspace.com/planetarchh <-- my music

My stuff: torus.untergrund.net <-- some diy electronic stuff and more.

#13 .oisyn

    DevMaster Staff

  • Moderators
  • 1810 posts

Posted 24 February 2007 - 10:35 PM

When you use shared memory (keyword: memory mapped files), both processes can read and write to that memory simultaneously. Also, you can make the OS to map that memory onto a specific address within your address space, and if both processes map using the same address, you can even use regular pointers (as long as they point to data within the shared memory region of course)
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#14 celu

    New Member

  • Members
  • PipPip
  • 20 posts

Posted 25 February 2007 - 04:10 PM

I have a DirectX application(process A) that needs to use an array created by maya plugin(process B).Process B updates this array continuously,and Process A needs to read this updated information from this array during each frame.I wanted the most efficient way of getting this array data from Process B to Process A. Process B only writes to the array and Process A only reads from the array.I thought of creating a global memory block in process B,copy the array on to this block.Then pass the handle to this global memory block to process A(using named pipes).Once i receive the handle in process A.I could then lock it to read the array data from the global memeory block into Process A.This way Process A could read this memory block when ever it needs to by locking & unlocking it and process B could write to it in the same way.I think this would be better than using named pipe for passing the entire array between the two processes during each frame.Moreover passing the array between the processes at frame rate speeds using named pipes would introduce synchronizing delays that might affect the frame rate init? By passing the memory handle I need to use the named pipes only at the start(to pass the memory handle).After that, the two process will have their own copy of the global memory block handle.And process B can write to that memory block and process A can read from it.At frame rate speeds this would be better init?

#15 Reedbeta

    DevMaster Staff

  • Administrators
  • 4782 posts
  • LocationBellevue, WA

Posted 25 February 2007 - 06:51 PM

Well, global memory blocks can only be locked by one process, so you'd need some kind of synchronization mechanism between the two to know when you can pass control. Maybe you should use memory-mapped I/O instead; see CreateFileMapping (passing INVALID_HANDLE_VALUE for the first argument lets you create a named mapping object that can be shared, rather like a named pipe). You should be able to map a view of the file in both processes and use this as shared memory without the need to lock/unlock (though you'll have to keep a synchronization bit in the data, or use a mutex or similiar to prevent race conditions).
reedbeta.com - developer blog, OpenGL demos, and other projects

#16 .oisyn

    DevMaster Staff

  • Moderators
  • 1810 posts

Posted 25 February 2007 - 11:35 PM

Also, a shared memory handle and mutices can be created and opened using global names. That way, you don't have to pass handles to the other application using named pipes or whatever (which are tedious for non-global handles like a mutices, as you first have to duplicate the handle for the other process)
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#17 celu

    New Member

  • Members
  • PipPip
  • 20 posts

Posted 26 February 2007 - 12:32 PM

ya i think memory-mapped I/O will fit my needs correctly...think ill have to remove the pipes and redo my app with memory mapped I/O..will keep you updated on the progress and thx a lot all you guys :)

#18 saqibbs

    New Member

  • Members
  • Pip
  • 2 posts

Posted 19 March 2007 - 05:24 PM

My problem is very similar to what the original poster intended to do in the first place.

I have two processes A and B, A passes some data to B through named-pipe, (in reality it is passing a pointer to some data in A's memory space) so when B receives the data, it gets the correct value of the pointer, but the pointer which B received doesn't point to a memory location in A's memory space. (I know this because the data accessed by B's pointer received from A is not the same value assigned by A before passing the pointer)

Here are two points.

i) My understanding is that process A and B don't share the same memory space hence passing pointers to each other is fruitless so I need to set up shared memory between A&B (I need confirmation on this point)

ii) But looking at a driver code, this is exactly what is being done, when I need to read from a device, I pass a pointer to the location where I want the data from the device and the driver returns when it has written data in that location. The location where I want my data to be stored is of course in my memory space but the driver is stable able to access that space.
(so my understanding is that in (ii) it happens because the driver is under the kernel-control so kernel allows such things but two processes in user-space aren't allowed to do such things)

I have modified a small client-server model taken from ,
http://developers.su...d_pipes.html#2a
which proves one, but I need confirmation that what I have done is correct and what I have concluded is correct too.

Thanks

Server CODE:
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "full_duplex.h" /* For name of the named-pipe */

int main(int argc, char *argv[])
{
    int rdfd, wrfd, ret_val, count, numread;
    char buf[MAX_BUF_SIZE];

    unsigned long *buff;
    int *buffPtr;
    buff = (unsigned long *)buf;

    ret_val = mkfifo(NP1, 0666);

    if ((ret_val == -1) && (errno != EEXIST)) {
        perror("Error creating the named pipe");
        exit (1);
    }

    /* Open the first named pipe for reading */
    rdfd = open(NP1, O_RDONLY);

    /* Read from the first pipe */
    numread = read(rdfd, buf, MAX_BUF_SIZE);
    printf("Num Read %d %ld\n", numread, buff[0]);

    buffPtr = (int *)buff[0];

    printf("%ld\n", buffPtr);
    printf("%d\n", *buffPtr);

}

Client CODE:

#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "full_duplex.h" /* For name of the named-pipe */

int main(int argc, char *argv[])
{
    int wrfd, rdfd, numread, sample;
    int *address;
    char rdbuf[MAX_BUF_SIZE];
    unsigned long *buff;

    address = &sample;
    sample = 33;
    buff = (unsigned long *)rdbuf;
    buff[0] = (unsigned long)&sample;

    printf("%d %ld %ld\n", sample, &sample, buff[0]);


    /* Open the first named pipe for writing */
    wrfd = open(NP1, O_WRONLY);

    /* Write to the pipe */
    write(wrfd, rdbuf, 8);

    exit(0);

}


#19 Reedbeta

    DevMaster Staff

  • Administrators
  • 4782 posts
  • LocationBellevue, WA

Posted 19 March 2007 - 05:27 PM

Okay, first of all, please use the code tags when you post code. I have added them for you this time.

Now as for your question.
(i) Yes.
(ii) Yes.
reedbeta.com - developer blog, OpenGL demos, and other projects

#20 saqibbs

    New Member

  • Members
  • Pip
  • 2 posts

Posted 21 March 2007 - 10:42 PM

Thanks for clearing that up. Here are a few more questions.

So in my client code I created any anonymous memory segment which was supposed to be shared, (i used mmap to create it) and then I passed to pointer to this memory the server, and the pointer value on the server side is the same as the client yet the data doesn't match.

i) In Stevens book (Unix Networking, IPC) the memory is shared across child and parent

ii) How can we share memory between two unrelated processes.

iii) Should I use System V IPC (shmget, shmid etc) compared to using BSD sharing (mmap)??

Thanks





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users