UDN
Search public documentation:
DLLBind
日本語訳
中国翻译
한국어
Interested in the Unreal Engine?
Visit the Unreal Technology site.
Looking for jobs and company info?
Check out the Epic games site.
Questions about support via UDN?
Contact the UDN Staff
中国翻译
한국어
Interested in the Unreal Engine?
Visit the Unreal Technology site.
Looking for jobs and company info?
Check out the Epic games site.
Questions about support via UDN?
Contact the UDN Staff
UE3 Home > UnrealScript > Calling DLLs from UnrealScript (DLLBind)
Calling DLLs from UnrealScript (DLLBind)
Overview
UnrealScript side
DLLBind
directive, and the DLL name to bind to is specified in parentheses. Do not include a path or .DLL extension. DLLs can only be loaded from the Binaries\Win32\UserCode folder.
Imported functions are declared like UnrealScript functions using the dllimport
function directive.
DLL import functions must be declared final, and it is not possible to create a subclass of a DLLBind class.
For example:
class TestDLLPlayerController extends PlayerController DLLBind(TestDLL); dllimport final function CallDLL1(out string s); dllimport final function vector CallDLL2(float x, float y, float z); dllimport final function bool CallDLL3(string s, int i[2], out float f, out vector v);When the TestDLLPlayerController class is loaded, it will bind to Binaries\Win32\UserCode\TestDLL.dll. If the DLL cannot be bound, a warning will be printed in the log. It will attempt to find entry points to three exports in the DLL (CallDLL1, CallDLL2 and CallDLL3). Once bound, these functions can be called as normal from other UnrealScript functions. If the bind fails, making a call to one of these functions will have no effect.
DLL side
extern "C" { struct FVector { float x,y,z; }; __declspec(dllexport) void CallDLL1(wchar_t* s) { MessageBox(0, s, L"Inside the DLL: CallDLL1", MB_OK); // reverse the out parameter string int len = wcslen(s); for(int i=0; i<len>>1;i++) { wchar_t temp = s[i]; s[i] = s[len-i-1]; s[len-i-1] = temp; } } __declspec(dllexport) FVector* CallDLL2(float x, float y, float z) { static FVector result; // declared static so that the struct's memory is still valid after the function returns. result.x = x; result.y = y; result.z = z; return &result; } __declspec(dllexport) bool CallDLL3(wchar_t* s, int i[2], float* f, FVector* V) { wchar_t temp[1024]; swprintf_s(temp, 1024, L"string: %s, i: {%d,%d}, float: %f, V was (%f,%f,%f)", s, i[0], i[1], *f, V->x, V->y, V->z); V->x = (float)i[0]; V->y = (float)i[1]; V->z = (*f); return (MessageBox(0, temp, L"Inside the DLL: CallDLL3", MB_OKCANCEL) == IDOK); } }
Unloading
Supported Parameter Types
UnrealScript type | C type | |
int value | int value (32-bit) | passed by value |
int value[..] | int* value (32-bit) | passed by reference |
out int value | int* value (32-bit) | passed by reference |
float value | float value | passed by value |
float value[..] | float* value | passed by reference |
out float value | float* value | passed by reference |
byte value | unsigned char value | passed by value |
byte value[..] | unsigned char* value | passed by reference |
out byte value | unsigned char* value | passed by reference |
string value | wchar_t* value | passed by reference |
out string value | wchar_t* value | passed by reference SEE WARNINGS BELOW |
struct foo | struct foo* value | passed by reference. The DLL should declare a struct to match the UnrealScript struct. See below for information about strings inside the struct. |
out struct foo | struct foo* value | passed by reference |
UnrealScript type | C type | |
int | int (32-bit) | returns value directly |
float | float value | returns value directly |
byte | unsigned char | returns value directly |
bool | unsigned int (32-bit) | returns value directly, non-zero is true |
string | wchar_t* | pointer value is strcpy'd into a UnrealScript string. SEE WARNINGS BELOW |
struct foo | struct foo* | struct data is memcpy'd into the UnrealScript struct. SEE WARNINGS BELOW |
Limitations
- Only Unicode (UTF-16) strings are supported. Compile your DLL with Unicode enabled.
- As only the 32-bit version of UDK is currently available, only 32-bit DLLs are supported. At such time as a 64-bit version of UDK is available, 64-bit DLLs will be supported.
- DLLs can only be loaded from Binaries\Win32\UserCode.
- Under Win32, only stdcall is supported. (See this link for information about calling conventions).
Debugging
- A Debug build of your DLL should bind correctly, and you should be able to attach to UDK.exe with your debugger and set breakpoints in your DLL.
- You should compile your DLL in Release mode if you intend to distribute it to others, otherwise you will likely have problems as the debug version of the C runtime will be unavailable.
About UnrealScript strings, and using strings inside structs
- Data, a 32-bit pointer to the memory allocated for the string
- ArrayNum, a 32-bit int storing the current number of 16-bit WORDs (UTF-16 characters) in the string (including the NULL terminator). This is normally equal to wcslen(Data)+1 except in empty strings, where it is 0.
- ArrayMax, a 32-bit int storing the number of 16-bit WORDs of memory currently allocated for the string.
struct FString { wchar_t* Data; int ArrayNum; int ArrayMax; }; struct MyPlayerStruct { FString PlayerName; FString PlayerPassword; float Health; float Score; };UnrealScript:
struct MyPlayerStruct { var string PlayerName; var string PlayerPassword; var float Health; var float Score; };Notes
- If the struct is an out parameter, it is possible to change the value of the strings inside the struct up to the length of ArrayMax, provided you adjust ArrayNum to match afterwards. See the StringDLL example attached.
- Do not attempt to allocate or reallocate the Data pointer, as your DLL will not use Unreal's memory allocator.
- Do not adjust the ArrayMax value.
- Do not return structs with strings because Unreal will attempt to free the Data memory when the struct variable is destroyed.
Warnings
- When modifying a string out parameter, the new string must be the same length or shorter than the previous value of the string passed in. This can be achieve by initializing the string in UnrealScript to something longer than the maximum value the DLL will store. Failure to do this will likely overwrite memory and cause a crash.
- When returning structs or strings, the DLL returns a pointer and Unreal will copy the value back to UnrealScript. However the DLL is responsible for allocating the memory to store the data pointed to. For example, it could return a pointer to a static variable, as is done in CallDLL2. Returning a pointer to a variable declared on the stack will result in corrupt data or a crash, because the stack is destroyed when the DLL function returns.
- In UnrealScript struct members are aligned on 4-byte boundaries, so you should use the /Zp4 compiler option when building your DLL.
- It is possible to declare structs containing Unreal data types that the DLL cannot understand. It is not recommended you do this!
- Do not attempt to return a struct containing UnrealScript strings. Out parameters are OK if you follow the directions above.
- Prior to February 2010 UDK, the current working directory was set to the Binaries\Win32 folder and NOT UserCode. Since the February 2010 version, the working directory is changed to the UserCode folder before calling any DLLBind functions.
Example
- DLLBind_Example.zip - basic DLLBind example
- StringDLL.zip - example showing how to use structs with strings.
- ArrayDLL.zip - advanced example showing use of dynamic arrays inside the DLL including memory reallocation.