Updated 2014-02-09 18:06:25 by dkf

This is a very long shot posting but...

jbr 2012-09-27.

I'm trying to control a particular application, Zemax, via its DDE interface. Everything mostly works. It uses the DDE Request Item interface for all its interactions. I can query values from it and that works fine. When I send requests to "Set" values or effect commands the requests return correct status values, but they don't actually take effect. There is something not quite right when the DDE request originates from Tcl.

The issue seems to have to do with Tcl itself or some attribute of the Tcl executable. I've tried with Active Tcl 8.5.12 and a Tclkit that I downloaded from somewhere.

Any ideas about how I could further debug this issue would be appreciated.

If I compile this code as a stand alone program with gcc I can control Zemax just fine:
      > i686-w64-mingw32-gcc -o dde.exe dde.c
#include <stdio.h>

#include <windows.h>
#include <dde.h>
#include <ddeml.h>

char *ddeRequest(DWORD ddeInstance, HCONV ddeConv, char *request)
{
    HSZ ddeItem;
    HDDEDATA ddeData;
    DWORD tmp;

    ddeItem = DdeCreateStringHandle(ddeInstance, request, 0);

    ddeData = DdeClientTransaction(NULL, 0, ddeConv, ddeItem, CF_TEXT, XTYP_REQUEST, 5000, NULL);

    DdeFreeStringHandle(ddeInstance, ddeItem);

    char *dataString = strdup((const char *) DdeAccessData(ddeData, &tmp));

    printf("%s\n", dataString);

    DdeUnaccessData(ddeData);
    DdeFreeDataHandle(ddeData);

    return dataString;
}

main(int argc, char *argv[]) {
    DWORD ddeInstance = 0;
    HSZ ddeTopic, ddeService, ddeItem;
    HCONV ddeConv;
    int i;

    if ( DdeInitialize(&ddeInstance, NULL, 0x00000010, 0) != DMLERR_NO_ERROR ) {
        fprintf(stderr, "Fail to Initialize\n");
        exit(1);
    }

    ddeService = DdeCreateStringHandle(ddeInstance, argv[1], 0);
    ddeTopic   = DdeCreateStringHandle(ddeInstance, argv[2], 0);

    ddeConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);

    DdeFreeStringHandle(ddeInstance, ddeService);
    DdeFreeStringHandle(ddeInstance, ddeTopic);

    for ( i = 3; i < argc; i++ ) {
        ddeRequest(ddeInstance, ddeConv, argv[i]);
    }

    exit(0);
}

If I use the built in dde package or compile this code (similar to the above) with a mingw cross compiler under critcl I get the exact same status responses from Zemax, but nothing actually changes in the application.
critcl::ccode {
    #include <windows.h>
    #include <dde.h>
    #include <ddeml.h>
}

critcl::cproc dderequest { Tcl_Interp* ip char* app char* top char* item int timeout } char* {
    DWORD ddeInstance = 0;
    HSZ ddeTopic, ddeService, ddeItem;
    HCONV ddeConv;

    HDDEDATA ddeData;
    DWORD tmp;

    if ( DdeInitialize(&ddeInstance, NULL, 0x00000010, 0) != DMLERR_NO_ERROR ) {
        fprintf(stderr, "Fail\n");
    }

    ddeService = DdeCreateStringHandle(ddeInstance, app, 0);
    ddeTopic   = DdeCreateStringHandle(ddeInstance, top, 0);

    ddeConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);

    DdeFreeStringHandle(ddeInstance, ddeService);
    DdeFreeStringHandle(ddeInstance, ddeTopic);


    ddeItem = DdeCreateStringHandle(ddeInstance, item, 0);

    ddeData = DdeClientTransaction(NULL, 0, ddeConv, ddeItem, CF_TEXT, XTYP_REQUEST, 5000, NULL);

    DdeFreeStringHandle(ddeInstance, ddeItem);

    char *dataString = strdup((const char *) DdeAccessData(ddeData, &tmp));

    DdeUnaccessData(ddeData);
    DdeFreeDataHandle(ddeData);

    return dataString;
}