Sie sind auf Seite 1von 13

DIgSILENT

PowerFactory 2018

DPL Extension Interface

I N T EG R AT E D P O W E R S Y S T EM A N A LY S I S S O F T WA R E F O R
T R A N S M I S S I O N / D I S T R I BU T I O N / I N D U S T RY / G EN E R AT I O N / I N T EG R AT I O N O F R EN E WA B L E S
Publisher:
DIgSILENT GmbH
Heinrich-Hertz-Straße 9
72810 Gomaringen / Germany
Tel.: +49 (0) 7072-9168-0
Fax: +49 (0) 7072-9168-88
info@digsilent.de

Please visit our homepage at:


http://www.digsilent.de

Copyright © 2017 DIgSILENT GmbH


All rights reserved. No part of this
publication may be reproduced or
distributed in any form without written
permission of DIgSILENT GmbH.

October 27, 2017


PowerFactory 2018
Revision 2
Contents

Contents

1 Introduction 1

1.1 Name and location of the external DLL . . . . . . . . . . . . . . . . . . . . . . . . 1

2 Format of the DLL 1

2.1 Header files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

2.2 Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

2.3 User-defined functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

2.3.1 Passed parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

2.3.2 Checkonly flag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.3.3 Returning results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.3.4 Status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.4 Printing messages to the Output Window . . . . . . . . . . . . . . . . . . . . . . 3

2.5 Directories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

3 Steps to create a new user-defined function 4

4 DLL Management (ComDllmanager) 4

5 Annexes 6

5.1 digdplarg.hpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

5.2 Example functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

DIgSILENT PowerFactory 2018, PowerFactory External DPL Functions i


2 Format of the DLL

1 Introduction

The built-in PowerFactory scripting language DPL can be extended by user-defined functions.
Those functions must be provided as a standard DLL following some specific implementation
requirements.

Functions implemented in those DLL are registered in the DPL interpreter and can be used
like built-in functions. The loading and registering process is executed once the first time the
interpreter meets an unknown function.

Please note: Displaying graphical user interfaces (e.g. dialogs, windows forms) inside user-
defined functions is not supported!

1.1 Name and location of the external DLL

The DPL interpreter searches for DLLs whose names start with digdplfun and end with .dll in
the PowerFactory installation directory. All of these DLLs are loaded at runtime of the DPL
interpreter.
If the first try to load such a DLL fails, no further attempts are made.
If multiple DLLs provide a function of same name, a warning is report and this function is not
registered.
The loading order is undefined.

2 Format of the DLL

The DLL is a standard MS Windows library having pure C functions exported by name.

2.1 Header files

In order to work with the arguments delivered by PowerFactory , the header digdplarg.hpp
must be included into the DLL. This header provides

• message output codes for printing messages to the output window of PowerFactory ,
• error enums for setting the execution status,
• structure of passed arguments and
• structure of returned result.

2.2 Initialization

The DLL must provide the following functions that are called in the registration process by the
DPL interpreter:

First, an init function with the following signature is called


void __cdecl Init(const char* _pWorkingDir,
const char* _pTempDir, FP_PRINTMSG _pPrintFnc)

DIgSILENT PowerFactory 2018, PowerFactory External DPL Functions 1


2 Format of the DLL

The passed arguments are

• the working directory of PowerFactory ,

• a temporary directory for storing temporary data and


• a function pointer to an output function of PowerFactory .

Hint: These arguments should be remembered for later usage.

Afterwards, the function RegisterFunctions is called


DIGDPLFUN_API RegisterFunctions(int iFncNr, char* cName)

This function publicizes all functions names. It’s called by the interpreter with increasing iFncNr.
A return of value ”0” means that additional functions are available for registration. A value of ”1”
ends this registration process.

Normally, the default implementations given in the attached example can be used without further
adaptation.

2.3 User-defined functions

Each user-defined DPL command must be implemented as a single function in the DLL provid-
ing the following signature:
DIGDPLFUN_API void FunctionName (DplArgList* argList, int checkonly,
ExtProcRes &result, ProcResTp &status)

Whenever such a user-defined function is called in a DPL script, the corresponding function in
DLL is executed. The parameters have the following meaning

• DplArgList* args: Delivers all arguments that are passed to the DPL command.

• int checkonly: Indicates if the function should only do an argument check.


• ExtProcRes &result: Result of the execution.
• ProcResTp &status: This is an output parameter indicating the success of the command
execution and indicating the type of the result value.

Please note that all function names are case-sensitive. Its not possible to overwrite a built-in
function.

2.3.1 Passed parameters

Parameters passed to the DPL function call (e.g. function(param1, param2, )) are stored in
the structure DplArgList* args. For external DPL functions only parameters of type double and
string can be accessed (integers are always passed as doubles). The sequences of elements
are the same as in DPL function call.

DIgSILENT PowerFactory 2018, PowerFactory External DPL Functions 2


2 Format of the DLL

2.3.2 Checkonly flag

When a script is executed, the DPL interpreter first performs a syntax check. For this check, all
functions are executed with flag checkonly set to 1. This means, the function should not do any
processing but just check the validity of given arguments. If the arguments seem to be okay, the
status must be set to ISOK or (if a result will be returned) to the type of the result delivered by
this function (e.g., a function that returns a double value must return ISDBL). If any argument is
detected as invalid, the status has to be set to ISARGERR.

2.3.3 Returning results

A result is returned by setting the result parameter. It is possible to return an integer, a double or
a string (as defined in ExtProcRes struct). The status parameter is used to indicate the type of
the result value. Attention, for returning a string the characters must be copied into the allocated
memory of result struct. It is necessary to ensure, that the string is zero terminated and does
not exceed a maximum of 1024 characters

2.3.4 Status

Setting the status variable has 2 relevancies:

First, it is used to indicate a fatal error to the DPL interpreter. This is done by setting the value
to ISERR.

Second, on success of execution, it indicates the type of the returned value. So the status must
be set to ISINT, ISDBL or ISSTR when returning a value. If no value is returned, it must be set
to ISOK.

2.4 Printing messages to the Output Window

In the initialization process, a function pointer is passed to the DLL. Via this function it is possible
to print messages to the output window of PowerFactory.

The print function has the signature


void print(const char* message, unsigned int messageType);

and expects 2 arguments:

• const char* message: The message to display.


• unsigned int messageType: Type of the message. Valid types are

– MSG PLAIN 0x0000 (no Digsi-, just like printf())


– MSG ERR 0x0001 (error)
– MSG WRNG 0x0002 (warning)
– MSG INFO 0x0004 (info)

DIgSILENT PowerFactory 2018, PowerFactory External DPL Functions 3


4 DLL Management (ComDllmanager)

2.5 Directories

When the DLL is loaded into PowerFactory , it is informed about the PowerFactory main
directory and a temp directory that can be used for storing temporary data. These paths are
given full qualified.

3 Steps to create a new user-defined function

A new function can be created by using attached example and following these steps:

1. Implement a function with given signature as described above


2. Add the function name to the array fncNames[]

4 DLL Management (ComDllmanager)

When a DLL is loaded its never freed up to the termination of PowerFactory . This means,
the DLL file keeps locked and cannot be replaced by another version while PowerFactory is
running.

This can be quite cumbersome for developing. Therefore, a so called hidden PowerFactory
command is available to load or unload external DLLs manually. This command is called
ComDllmanager and can be accessed by typing in the command name in the Element Selection
when creating a new element (it is not shown in a selection list) (see Figure 2).

The DLL manager supports loading and unloading of external DPL and DSL libraries. On
loading, these libraries must be located in the PowerFactory installation directory and named as
digdplfun*.dll (DPL) or digexdyn*.dll (DSL).

Furthermore, the DLL manager shows a list of currently loaded DLLs depending on selected
DLL type.

DIgSILENT PowerFactory 2018, PowerFactory External DPL Functions 4


4 DLL Management (ComDllmanager)

Figure 4.1: New object creation dialog.

Figure 4.2: Command to unload / load DLL manually.

DIgSILENT PowerFactory 2018, PowerFactory External DPL Functions 5


5 Annexes

5 Annexes

5.1 digdplarg.hpp

#define N_EXEPROC_ARG 64

#define MSG_PLAIN 0x0000


#define MSG_ERR 0x0001
#define MSG_WRNG 0x0002
#define MSG_INFO 0x0004

typedef enum {
ISVOID=0, ///< return value is void
ISERR, ///< error in function
ISOK, ///< everything seems to be OK
ISARGERR, ///< function arguments are wrong
ISSTR, ///< return value is a string
ISDBL, ///< return value is a double
ISINT ///< return value is a int
} ProcResTp;

struct DplArg {
ProcResTp typ;
union {
char *pStr;
double d;
int i;
void *ptr1;
void *ptr2;
void *ptr3;
void *ptr4;
};
DplArg() { typ=ISVOID; };
};

struct DplArgList {
int nArg;
DplArg Arg[N_EXEPROC_ARG]; ///< max N_EXEPROC_ARG function arguments
};

typedef union {
double d;
int i;
char s[1024];
} ExtProcRes;

5.2 Example functions

/***********************************************************************
* userfun.cpp: user-defined DPL functions
***********************************************************************/
/*
Defining new functions:
- add the function’s name to the array "fncNames"
- implement the function:

DIGDPLFUN_API void Function(DplArgList* argList, int checkonly, ExtProcRes &result,


ProcResTp &status)

DIgSILENT PowerFactory 2018, PowerFactory External DPL Functions 6


5 Annexes

args: arguments passed to the method call


checkonly: if "1", the function should only do a check on the arguments passed
and set ’status’ to ISARGERR on error. else, ’status’ has to be set
to result value type (e.g. ISDBL) or to ISOK if the function does not
return a value.
if not "1", the logic should be executed.
result: struct to store the result of the function call (e.g. returning a string,
int, double value)
status: holds the status of the method call
if any fatal error occured, it must be set to ISERR. else, it must be
set to the value return type of the function or to ISOK if there is
not return value.
*/

#include <stdio.h>
#include <string.h>

#include "digdplarg.hpp"

typedef void (__cdecl *FP_PRINTMSG)(const char*, unsigned int);

// call this function to print messages to the powerfactory output window


// pPrintFnc("message", type)
// where type can be MSG_ERR, MSG_WRNG, MSG_INFO
FP_PRINTMSG pPrintFnc;

// is set to working dir of powerfactory


char workingDir[256];

// is set to temp directory of powerfactory


char tempDir[256];

// register all functions here <---- add your functions here!


static char* fncNames[] = {
"Function1",
"Function2",
"Function3",
"Function4" };

// this method is called when loading dll into powerfactory


DIGDPLFUN_API void Init(const char* pWorkingDir, const char* pTempDir,
FP_PRINTMSG _pPrintFnc){
pPrintFnc = _pPrintFnc;
strncpy(workingDir, pWorkingDir, 256-1);
strncpy(tempDir, pTempDir, 256-1);
}

// registers functions as new dpl commands in powerfactory


DIGDPLFUN_API int RegisterFunctions(int iFncNr, char* cName)
{
// register userdefined functions number
// nb: name must be less than 512 characters!

if (iFncNr < sizeof(fncNames) / sizeof(char*)){


strncpy(cName,fncNames[iFncNr], 512-1);
return 0;
}

DIgSILENT PowerFactory 2018, PowerFactory External DPL Functions 7


5 Annexes

else{
return 1;
}
}

//----------------------------------------------------------------------------
//
// Implement your new DPL commands here !!
//
//----------------------------------------------------------------------------

// Example1
// The function doesn’t care for arguments. It just prints a message that it was
// called to the powerfactory output window.
DIGDPLFUN_API void Function1(DplArgList* argList, int checkonly, ExtProcRes &result,
ProcResTp &status)
{
status = ISOK; // set result type to everything ok
if (checkonly){
return;
}

pPrintFnc("Function1 called.",MSG_INFO);
}

// Example2
// The function shows how to access passed arguments.
DIGDPLFUN_API void Function2(DplArgList* argList, int checkonly, ExtProcRes &result,
ProcResTp &status)
{
status = ISOK;

// doing the argument check here


if (checkonly){
if (argList->nArg < 1){ //no arguments given
//consider this as error
status = ISARGERR;
}
return;
}

pPrintFnc("Function2 called.",MSG_INFO);

for (int i=0; i < argList->nArg; i++){

char text[512];
sprintf(text, "Argument[%i]:", i);
switch(argList->Arg[i].typ){
case ISSTR:
strcat(text, " (string) ");
strncat(text, argList->Arg[i].pStr, 400);
break;

case ISDBL:
char tmp[400];
sprintf(tmp, " (double) %f", argList->Arg[i].d);
strcat(text, tmp);

DIgSILENT PowerFactory 2018, PowerFactory External DPL Functions 8


5 Annexes

break;

case ISINT: // never used, integers transferred as doubles


sprintf(tmp, " (int) %i", argList->Arg[i].i);
strcat(text, tmp);
break;

default:
strcat(text, "Unknown type.");
status = ISERR;
}
pPrintFnc(text,MSG_INFO);

}
}

// Example3
// The function expects a variable number of double values and returns the sum
// of them.
DIGDPLFUN_API void Function3(DplArgList* argList, int checkonly, ExtProcRes &result,
ProcResTp &status)
{

status = ISDBL; //set the status to double to indicate that a double value
//will be returned

// doing the argument check here


if (checkonly){
if (argList->nArg < 1){ //no arguments given
//consider this as error
status = ISARGERR;
}
else {
for (int i=0; i < argList->nArg; i++){ //check if all args are of type double
if (argList->Arg[i].typ != ISDBL){
status = ISARGERR;
break;
}
}
}
return;
}

result.d = 0;
for (int i=0; i < argList->nArg; i++){
result.d += argList->Arg[i].d;
}
}

// Example4
// The function shows how to return a string.
DIGDPLFUN_API void Function4(DplArgList* argList, int checkonly, ExtProcRes &result,
ProcResTp &status)
{
status = ISSTR; //set return type to string

// doing the argument check here


if (checkonly){
if (argList->nArg > 0){ //no arguments are expected

DIgSILENT PowerFactory 2018, PowerFactory External DPL Functions 9


5 Annexes

status = ISARGERR;
}
return;
}

strcpy(result.s, "Hello World");


}

DIgSILENT PowerFactory 2018, PowerFactory External DPL Functions 10

Das könnte Ihnen auch gefallen