Zemax would normally publish such article in its Knowledge Base. But I think it should be significantly improved (outdated articles should be removed/rewritten, search should be improved, articles should be tagged and linked to each other, user comments should not get lost etc.), and until it is I’ll just publish my notes here.
One of the ways to expand Zemax functionality is by creating custom DLLs for objects, scattering, material, surface etc. Unfortunately, you’ll need something beyond basic knowledge on how to create a DLL in the IDE/compiler of your choice. Unless your DLL looks exactly the way Zemax expects it to look, the program will just ignore it, without any feedback. After some struggling, I’ve managed to make Zemax accept my DLL, and I list the required steps below, with some comments.
As the starting point, I’ve used the
C:\Program Files\Zemax\DLL\GradientIndex\grin1.c file provided by Zemax. I also tested this procedure with
Here are the steps needed to make Zemax 64 accept your DLL. The IDE I used was the free MS Visual Studio Express 2013 for Desktop.
- Create a new solution in VS. Create a new Visual C++ > Win32 > DLL project in it (http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w)
- Since Zemax is x64, we need a 64 bit DLL. Go to configuration manager and create a new x64 platform. Set it to active.
Note: To have it in VS 2010, see http://msdn.microsoft.com/en-us/library/9yb4317s(v=vs.100).aspx (something should be downloaded).
- Switch compilation mode to Release. Set Project > Properties (Alt + F7) > Configuration Properties > Linker > Debugging > Generate Debug Info for Release/x64 to NO (http://stackoverflow.com/a/2805812/674976)
- In Project > Properties > Configuration Properties > C/C++ > Preprocessor, add at the end of Preprocessor Definitions:
- In Project > Properties > Configuration Properties > C/C++ > Precompiled Headers, set Precompiled Header to an empty value (it can be Yes be default). Taken from http://stackoverflow.com/questions/7261707.
- Note the
lines I added to the code. This comes from http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w
This issue is also addressed (and explained in more details) here: http://www.ni.com/white-paper/3056/en/.
This command is only needed if the the source file has the .cpp extension. For .c it is not needed.
- The DLL should be copied to
C:\Program Files\Zemax\DLL. It requires Administrator rights on the computer.Note that the output DLL is in
I don’t know why.
The following steps are optional:
- Note that I removed the
int __declspec(dllexport) APIENTRY UserGrinDefinition(double *data);
int __declspec(dllexport) APIENTRY UserParamNames(char *data);
lines at the top. It also comes from the fact that they are not there in http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w
- To check why Zemax could not see the functions at first, I used the dumpbin tool.
It should be run from VS’s Command Line, which I could find nowhere. I’ve found how to add it to Tools here: http://stackoverflow.com/a/4245337/674976.
The required vcvarsall.bat file could be found in my case in
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC, although I am working with Visual Studio Express 2013. Not sure why.
With this set up, I could do
dumpbin /EXPORTS testDll.dll in the
x64/release directory and get:
C:\Users\xxx\x64\Release>dumpbin /EXPORTS testDll.dll
Microsoft (R) COFF/PE Dumper Version 12.00.21005.1
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file testDll.dll
File Type: DLL
Section contains the following exports for testDll.dll
536A6A96 time date stamp Wed May 07 19:17:10 2014
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 00001010 UserGrinDefinition
2 1 00001270 UserParamNames
- Note that if the DLL is compiled with Visual Studio >2010, it cannot be used on computers with only 2010 distributables. In this case, the distributable DLL can be
- statically linked to the DLL, thus removing the dependence. This is done in VS 2013 in Project Properties (Alt + F7) > Configuration Properties > C/C++ > Code Generation > Runtime Library,
which should be set to Multi-threaded (/MT) from the default Multi-threaded DLL (/MD).
With these modifications, Zemax accepted the DLL and could read the parameter names. I have not tried any calculations so far.
Full source code of the final file (testDll.cpp):
Written by Kenneth E. Moore
May 11, 2000
Modified January 24, 2005 to support rectangular periodic arrays
Modified 2014-05-07 by Kotya Karapetyan as a test Zemax 64 DLL project. Renamed to testDll.cpp.
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
extern "C" // taken from http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w, is needed to remove C++ symbol decoration, see http://www.ni.com/white-paper/3056/en/
int __declspec(dllexport) APIENTRY UserGrinDefinition(double *data)
double r, r2, index, N, A, B, x, y, dx, dy;
N = data;
A = data;
B = data;
dx = data;
dy = data;
x = data;
y = data;
if (dx > 0 && dy > 0)
// adjust to center of array
if (x > +0.5*dx) x -= dx*(double)ceil(+(x - 0.5*dx) / dx);
if (x < -0.5*dx) x += dx*(double)ceil(-(x + 0.5*dx) / dx);
if (y > +0.5*dy) y -= dy*(double)ceil(+(y - 0.5*dy) / dy);
if (y < -0.5*dy) y += dy*(double)ceil(-(y + 0.5*dy) / dy);
r2 = x*x + y*y;
r = sqrt(r2);
index = N + A*r2 + B*r;
data = index;
if (index < 1.0)
/* now the derivatives, note they are multiplied by index */
data = 2.0*A*x*index;
data = 2.0*A*y*index;
if (B != 0.0 && r > 0.0)
data += B*x*index / r;
data += B*y*index / r;
data = 0.0;
int __declspec(dllexport) APIENTRY UserParamNames(char *data)
/* this function returns the name of the parameter requested */
i = (int)data;
if (i == 1) strcpy(data, "N0");
if (i == 2) strcpy(data, "Nr2");
if (i == 3) strcpy(data, "Nr1");
if (i == 4) strcpy(data, "Array dx");
if (i == 5) strcpy(data, "Array dy");
if (i == 6) strcpy(data, "K"); // added by Kotya for testing 2014-05-07
See also related Knowledge Base articles: How to compile an extension using MS Visual Studio Express 2012, Compiling a 64-bit Application in Microsoft Visual Studio Express 2010 (note: I haven’t checked them for correctness).