From: Joseph M. Newcomer on
If you need a DLL that is called from matlab itself, and it is supposed to represent an
application, I'd be inclined to do one of the following:

* Have the DLL SendMessage(WM_COPYDATA) to an instance of an application.

* Have the DLL use a shared memory segment to send data to the application, probably
using a semaphore to indicate something has been enqueued. The application will wait for
this semaphore in a separate thread and notify the app when the data arrives.

* Same as above, using a memory-mapped file to do the sharing.

* Use a simple message to send small quantities of data across using PostMessage (or
PostThreadMessage if sent to a non-GUI UI thread of the other app)

Partly, it depends on the amount of data. For very small amounts of data, a simple
PostMessage to the app will suffice (it can send a pair of floats, two integers, etc. in
one message). This does not scale up to massive data arrays.

Shared memory should be treated with respect, in that you should not be doing much
locking. I prefer the "positive handoff" protocol where you fill something up, and put it
in an "inbox" for the other app. The only locking you need to do is in manipulating the
allocation of the shared data values within the shared data segment, which is easier and
safer to do than trying to lock entire data areas for long periods of time. Once a data
block is allocated, it is either used by the "producer" that writes into it, or by the
"consumer" that reads from it, but there is NEVER concurrent access to the data, under any
circumstances. The only concurrent access is protecting the allocator.
joe

On Sun, 11 May 2008 11:50:57 -0700, "David Ching" <dc(a)remove-this.dcsoft.com> wrote:

>"Scott McPhillips [MVP]" <org-dot-mvps-at-scottmcp> wrote in message
>news:%23V3juM5sIHA.5832(a)TK2MSFTNGP02.phx.gbl...
>> Here's a suggestion you might want to try, either as a permanent solution
>> or perhaps as an experiment to see what you can learn about the OnClose
>> problem. You could create a new (MFC) thread in the call from Matlab.
>> That's done by deriving a class from CWinThread and calling AfxBeginThread
>> with the class name.
>>
>> The thread has an InitInstance, just like your original application did,
>> and all of your windows etc. would run in the new thread if you put your
>> original InitInstance code there. The call from Matlab would merely sit
>> suspended in a WaitForSingleObject until the thread exits. The advantage
>> is that this would get you out of undocumented territory, and it would
>> start your thread and message pump (the Run function) using the normal MFC
>> initialization code.
>>
>
>It's a good idea to start the secondary thread to wait for the window to
>close. But I don't think it's proper behavior to call CWinApp::Run() from
>the 'hook' function. That seems plain wrong. It's already been called when
>the DLL was loaded and I've never seen it called again. So I would ditch
>the idea of calling CWinApp::Run().
>
>But everything else sounds good. Just move everything that was in the
>CWinApp::InitInstance() to the CMyWinThread::InitInstance(), then start it
>in the hook function using AfxBeginThread(), then WaitForSingleObject() of
>that thread.
>
>The reason I suggested just executing the .exe was because there was no sign
>of any data passing anywhere. I guess that is done through other exported
>functions that haven't been shown.
>
>-- David
>
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: JRGlide on

David, Scott, Ajay,

Thank you very much for your help. I will try your suggestion for the
WinThread and see how it works. That sounds like that may be what I need.

Scott, you said “The advantage is that this would get you out of
undocumented territory”. I was surprised to read that. I thought what I was
trying to do was pretty normal and done all the time. Is this not the case?
I am really in uncharted territory?

> The reason I suggested just executing the .exe was because there was no sign
> of any data passing anywhere. I guess that is done through other exported
> functions that haven't been shown.

Sorry about that, David. I tried to trim it down so I didn't include a lot
of unnecessary code, but maybe I cut it down too much. Here is a more
complete version of the calling routine (but still some cut out some).


typedef struct {
float x;
float y;
float z;
float intensity;
unsigned char clipped;
} IMAGE_DATA;

extern "C" {

__declspec(dllimport) IMAGE_DATA *point_cloud;
__declspec(dllimport) int num_points;
__declspec(dllimport) int ViewPointCloud (void);

}


int main (int argc, char* argv[])
{
IMAGE_DATA *point_cloud;

// Read data here. This would normally be passed in by MATLAB.

point_cloud = (IMAGE_DATA*) malloc (sizeof (IMAGE_DATA)*100000);
num_points = 100000;

ViewPointCloud();

free (point_cloud);
return 0;
}

Thanks again and I'll let you know how this works.

Jim


From: JRGlide on
Joe,

The purpose of the viewer is to provide another tool for MATLAB (and
LabView) users for viewing data, just as plot2d, plot3d and surf allow the
user to view data in different ways. This is a research facility so the
MATLAB programs are always changing. This is why the user needs to call my
viewer and not the other way around. Actually, MATLAB has the ability to
view and rotate 3D data, but it is dirt slow, which is why I came up with
this idea. I already had a standalone program and I thought it would be easy
to convert it to a dll, and call it from a MATLAB mex function.

The sequence was suppose to be that the MATLAB user would call a mex
function I wrote called “mxViewPointCloud” which in turn called
“ViewPointCloud” within the MFC app, which was suppose to pass the data to
the viewer. At least that was the theory…

I will try the ideas you suggested and also the WinThread idea. The data
passing is indeed one-way as you cautioned, since it is strictly for display.
However, it is a large amount of data. It can be anywhere from a few
hundred thousand to millions of points. A million points requires 40 Meg of
data be passed along.

Thank you for your help.

Jim


"Joseph M. Newcomer" wrote:

> A DLL is a DLL. A .exe is a .exe. You can't magically convert one to the other.
>
> Generally, since matlab output can be made into a subroutine, I'd be more likely to write
> an MFC app that called a matlab subroutine, rather than a matlab application that called
> an MFC DLL that pretended to be an entire app. I have two clients right now who use
> matlab, one for signal processing and one for signal conditioning, and what they send me
> is matlab code in a DLL, which seems a lot more sensible as an approach. The advantage of
> doing the DLL is that if they tweak the algorithms, we can distribute new DLLs and
> everyone gets the tweak without any changes to the interface.
>
> It sounds to me like you are approaching the problem from the wrong direction.
> joe



From: Joseph M. Newcomer on
Yes. It is extremely uncommon to try to build an application and its message loop into a
DLL.

There are three components here that are invovled, as I've understood it:
MATLAB mathematics
Rendering an image
Window management

The question is, why do you need to incorporate window management with your rendering
algorithm? Doesn't MATLAB already provide a window management capability? So all you
should need to do is pass a window handle (HWND) into your DLL (and MATLAB probably wraps
this in some higher-level graphical object so it can be platform-independent, but when
running on Windows, there should be a way to extract the base graphical object). So you
pass this window-representative into your DLL, which immediately subclasses WM_PAINT and
WM_NCDESTROY. For WM_PAINT, you do your rendering, which is based on whatever information
you passed into your DLL as a data call. For WM_NCDESTROY you unsubclass the window. The
message loop of MATLAB should be dispatching.

The alternative, to use a UI thread, is not unreasonable. But what it represents is a
thread with a GUI interface, *NOT* a full-scale application. It is more self-contained
but it in no way resembles a full app.


On Sun, 11 May 2008 14:18:00 -0700, JRGlide <JRGlide(a)discussions.microsoft.com> wrote:

>
>David, Scott, Ajay,
>
>Thank you very much for your help. I will try your suggestion for the
>WinThread and see how it works. That sounds like that may be what I need.
>
>Scott, you said �The advantage is that this would get you out of
>undocumented territory�. I was surprised to read that. I thought what I was
>trying to do was pretty normal and done all the time. Is this not the case?
>I am really in uncharted territory?
>
>> The reason I suggested just executing the .exe was because there was no sign
>> of any data passing anywhere. I guess that is done through other exported
>> functions that haven't been shown.
>
>Sorry about that, David. I tried to trim it down so I didn�t include a lot
>of unnecessary code, but maybe I cut it down too much. Here is a more
>complete version of the calling routine (but still some cut out some).
>
>
>typedef struct {
> float x;
> float y;
> float z;
> float intensity;
> unsigned char clipped;
> } IMAGE_DATA;
>
>extern "C" {
>
>__declspec(dllimport) IMAGE_DATA *point_cloud;
>__declspec(dllimport) int num_points;
>__declspec(dllimport) int ViewPointCloud (void);
>
>}
>
>
>int main (int argc, char* argv[])
****
This is where I have problems. You would not be calling 'main', you would be calling a
function in your DLL, whose name would almost certainly NOT be 'main'. It would have no
argc, no argv; it would be a function, and nothing more.
****
>{
> IMAGE_DATA *point_cloud;
>
>// Read data here. This would normally be passed in by MATLAB.
>
> point_cloud = (IMAGE_DATA*) malloc (sizeof (IMAGE_DATA)*100000);
> num_points = 100000;
****
Numbers like this, which are hardwired, scare me. It's not the 2MB, it's the fact that it
is fixed at compile time and isn't even a #define/static const (U)INT.

Forget 'main' or 'winMain' entirely, pretend you never heard of them. Then start working
forward from there.
joe

****
>
> ViewPointCloud();
>
> free (point_cloud);
> return 0;
>}
>
>Thanks again and I'll let you know how this works.
>
>Jim
>
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: JRGlide on
Today I tried using the CWinThread as David and Scott suggested, but I had
some problems. When I created my own CWinThread and moved my InitInstance
over from my CWinApp, I got undefines on all the Doc/View type calls, such as:

AddDocTemplate(pDocTemplate);
ParseCommandLine(cmdInfo);
ProcessShellCommand(cmdInfo)

I think this is because they are only defined in CWinApp and not in
CWinThread.

So then I started thinking that since CWinApp is derived from CWinThread,
that maybe I could just call AfxBeginThread and pass it the original
application instead, like this:

CViewPointCloudApp *pointCloudThread = (CViewPointCloudApp*) AfxBeginThread
(RUNTIME_CLASS (CViewPointCloudApp));

It sounds good in theory anyway, but I got undefines. The RUNTIME_CLASS
macro didn't like me passing an CWinApp instead of a CWinThread.

Did I understand you right, is this how I should be doing it?

Otherwise, my next idea is to either convert the program and get rid of the
Doc/View and go straight to a Frame and child window (I don't really need
Doc/View anyway). Or I will try Joes idea of passing the data in a global
memory structure and just using the viewer as an application rather than a
dll.


As for Joe's concerns about using a main function and hard-coding array
sizes. This is just another case of me making things more complicated by
trying to simplify things. The normal calling routine would be a MATLAB mex
(MATLAB Executable) function which is a non-MFC dll. But if I had included
the code for that, it would just clutter things up with all the MATLAB calls
I have to make to extract the called data. A simple main program shows the
basic calling sequence and are the exact same calls I would make from the mex
function.

Thank you again for your help,

Jim