├── pbsrc ├── b.cmd ├── Samples │ ├── BrowseForFolder │ │ ├── bb.cmd │ │ ├── debug │ │ │ ├── 1 │ │ │ ├── fa.exe │ │ │ ├── aaaaa.exe │ │ │ ├── fa1.exe │ │ │ ├── pbinvoke.pbd │ │ │ ├── libPBInvoke.dll │ │ │ ├── browseforfolder.pbd │ │ │ └── browseforfolder_demo.pbd │ │ ├── pbinvoke.pbl │ │ ├── libPBInvoke.dll │ │ ├── 2054_EBrowseF.zip │ │ ├── browseforfolder.pbl │ │ ├── browseforfolder_demo.pbl │ │ ├── update.cmd │ │ ├── browseforfolder.pbt │ │ ├── readme.txt │ │ └── default.pbc │ ├── SetWindowHook │ │ ├── pbinvoke.pbl │ │ ├── customsaveas.pbl │ │ ├── libPBInvoke.dll │ │ ├── setwindowshookdemo.pbl │ │ ├── update.cmd │ │ ├── setwindowshookdemo.pbt │ │ ├── readme.txt │ │ └── default.pbc │ └── enumwindows │ │ ├── pbinvoke.pbl │ │ ├── enumwindows.pbl │ │ ├── libPBInvoke.dll │ │ ├── enumwindows.pbt │ │ └── update.cmd ├── tester │ └── tester.pbl ├── pbinvoke │ ├── pbinvoke.pbl │ ├── build_pbinvoke.pbl │ ├── build_pbinvoke.pbt │ └── default.pbc ├── tester.pbt ├── w.pbw └── default.pbc ├── src ├── types │ ├── BoolType.cpp │ ├── IntType.cpp │ ├── BoolType.h │ ├── VoidType.h │ ├── RefType.cpp │ ├── RefType.h │ ├── ShortType.h │ ├── ArrayType.h │ ├── Int64Type.h │ ├── DoubleType.h │ ├── FloatType.h │ ├── TypeFactory.h │ ├── FloatType.cpp │ ├── Int64Type.cpp │ ├── DoubleType.cpp │ ├── IntType.h │ ├── ArrayType.cpp │ ├── DataTypes.h │ ├── PointerType.h │ ├── PointerType.cpp │ ├── StringType.h │ ├── RawType.h │ ├── MethodType.h │ ├── RawType.cpp │ ├── TypeFactory.cpp │ ├── StructType.h │ ├── CharType.h │ ├── StringType.cpp │ └── CharType.cpp ├── version.rc ├── parser │ ├── CParser.output │ ├── Declaration.cpp │ ├── Declaration.h │ ├── PrototypeDeclaration.cpp │ ├── build_lexer.cmd │ ├── PrototypeDeclaration.h │ ├── build_parser.cmd │ ├── CParser.hlp.h │ ├── clexer.h │ ├── stack.hh │ ├── clexer.l │ ├── location.hh │ ├── position.hh │ ├── ASTNode.h │ └── ASTNode.cpp ├── StdAfx.cpp ├── MethodInstance.h ├── PBException.cpp ├── PBException.h ├── Objects │ ├── Structure.h │ └── Structure.cpp ├── resource.h ├── WinHooks.cpp ├── DLLMethodInstance.h ├── WinHooks.h ├── DLLMethodInstance.cpp ├── PBCallback.h ├── Compiler.h ├── MethodInstance.cpp ├── PBInvoke.def ├── libPBInvoke.cpp ├── DynCallback.h ├── StdAfx.h ├── Core.h ├── Compiler.cpp ├── PBCallback.cpp ├── CallbackData.cpp └── Runtime.h ├── develdoc ├── net.txt ├── packing.txt ├── types.txt ├── synopsis.txt ├── marshalling.txt └── value-semantics.txt ├── doc ├── pbinvoke_en.chm ├── build_help.cmd ├── license.html ├── help.hhk ├── genhelp │ ├── help.hhk │ ├── help.hhp │ ├── unsupported.html │ ├── winapi.html │ ├── handling-tchar.html │ ├── help.hhc │ ├── supported-data-types.html │ ├── quick-start-guide.html │ ├── handling-strings.html │ ├── index.html │ ├── license.html │ ├── style.css │ └── working-with-structures.html ├── _template_help.html ├── help.hhp ├── _template_site.html ├── doc.html ├── unsupported.html ├── winapi.html ├── handling-tchar.html ├── gen_help.pl ├── handling-strings.html ├── supported-data-types.html ├── quick-start-guide.html ├── help.hhc ├── index.html ├── working-with-structures.html ├── style.css └── working-with-callbacks.html ├── .gitignore └── projects ├── libPBInvoke_vc9 ├── build_all.cmd ├── DLLMethodAddr.cpp ├── postbuild.cmd ├── ReadMe.txt └── libPBInvoke.sln └── tester1 ├── tester1.cpp ├── stdafx.cpp ├── stdafx.h └── ReadMe.txt /pbsrc/b.cmd: -------------------------------------------------------------------------------- 1 | call pb9 2 | pbc -p default.pbc -b -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/bb.cmd: -------------------------------------------------------------------------------- 1 | pbc -p default.pbc -r -b -------------------------------------------------------------------------------- /src/types/BoolType.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | 3 | #include "BoolType.h" -------------------------------------------------------------------------------- /src/types/IntType.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | 3 | #include "IntType.h" -------------------------------------------------------------------------------- /src/version.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/src/version.rc -------------------------------------------------------------------------------- /develdoc/net.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/develdoc/net.txt -------------------------------------------------------------------------------- /develdoc/packing.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/develdoc/packing.txt -------------------------------------------------------------------------------- /develdoc/types.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/develdoc/types.txt -------------------------------------------------------------------------------- /doc/pbinvoke_en.chm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/doc/pbinvoke_en.chm -------------------------------------------------------------------------------- /develdoc/synopsis.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/develdoc/synopsis.txt -------------------------------------------------------------------------------- /develdoc/marshalling.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/develdoc/marshalling.txt -------------------------------------------------------------------------------- /pbsrc/tester/tester.pbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/tester/tester.pbl -------------------------------------------------------------------------------- /src/parser/CParser.output: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/src/parser/CParser.output -------------------------------------------------------------------------------- /pbsrc/pbinvoke/pbinvoke.pbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/pbinvoke/pbinvoke.pbl -------------------------------------------------------------------------------- /develdoc/value-semantics.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/develdoc/value-semantics.txt -------------------------------------------------------------------------------- /doc/build_help.cmd: -------------------------------------------------------------------------------- 1 | set hhc=C:\Usr\App2\MsHtmlHelp\hhc.exe 2 | perl gen_help.pl 3 | pushd genhelp 4 | %HHC% help.hhp 5 | popd -------------------------------------------------------------------------------- /pbsrc/pbinvoke/build_pbinvoke.pbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/pbinvoke/build_pbinvoke.pbl -------------------------------------------------------------------------------- /pbsrc/Samples/SetWindowHook/pbinvoke.pbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/SetWindowHook/pbinvoke.pbl -------------------------------------------------------------------------------- /pbsrc/Samples/enumwindows/pbinvoke.pbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/enumwindows/pbinvoke.pbl -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/debug/fa.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/BrowseForFolder/debug/fa.exe -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/pbinvoke.pbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/BrowseForFolder/pbinvoke.pbl -------------------------------------------------------------------------------- /pbsrc/Samples/enumwindows/enumwindows.pbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/enumwindows/enumwindows.pbl -------------------------------------------------------------------------------- /pbsrc/Samples/enumwindows/libPBInvoke.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/enumwindows/libPBInvoke.dll -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/debug/aaaaa.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/BrowseForFolder/debug/aaaaa.exe -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/debug/fa1.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/BrowseForFolder/debug/fa1.exe -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/libPBInvoke.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/BrowseForFolder/libPBInvoke.dll -------------------------------------------------------------------------------- /pbsrc/Samples/SetWindowHook/customsaveas.pbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/SetWindowHook/customsaveas.pbl -------------------------------------------------------------------------------- /pbsrc/Samples/SetWindowHook/libPBInvoke.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/SetWindowHook/libPBInvoke.dll -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/2054_EBrowseF.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/BrowseForFolder/2054_EBrowseF.zip -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/browseforfolder.pbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/BrowseForFolder/browseforfolder.pbl -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/debug/pbinvoke.pbd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/BrowseForFolder/debug/pbinvoke.pbd -------------------------------------------------------------------------------- /pbsrc/Samples/SetWindowHook/setwindowshookdemo.pbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/SetWindowHook/setwindowshookdemo.pbl -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .svn 2 | *.log 3 | *.aps 4 | *.obj 5 | *.user 6 | *.suo 7 | *.ncb 8 | *.opt 9 | *.plg 10 | Release 11 | Debug 12 | ReleaseDemo 13 | -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/debug/libPBInvoke.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/BrowseForFolder/debug/libPBInvoke.dll -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/browseforfolder_demo.pbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/BrowseForFolder/browseforfolder_demo.pbl -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/debug/browseforfolder.pbd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/BrowseForFolder/debug/browseforfolder.pbd -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/debug/browseforfolder_demo.pbd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amoskovsky/pb-pbinvoke/HEAD/pbsrc/Samples/BrowseForFolder/debug/browseforfolder_demo.pbd -------------------------------------------------------------------------------- /doc/license.html: -------------------------------------------------------------------------------- 1 |

PBInvoke library license agreement

2 |
3 | 
4 | Author: Anatoly Moskovsky <avm@sqlbatch.com>
5 | License: Public Domain
6 | 
7 | 
8 | -------------------------------------------------------------------------------- /projects/libPBInvoke_vc9/build_all.cmd: -------------------------------------------------------------------------------- 1 | pushd %~dp0 2 | 3 | @rem set MS VC9 build environment 4 | @call vcv9 5 | 6 | devenv libPBInvoke.sln /build Release /project libPBInvoke 7 | 8 | popd -------------------------------------------------------------------------------- /projects/libPBInvoke_vc9/DLLMethodAddr.cpp: -------------------------------------------------------------------------------- 1 | #include "DLLMethodAddr.h" 2 | 3 | DLLMethodAddr::DLLMethodAddr(void) 4 | { 5 | } 6 | 7 | DLLMethodAddr::~DLLMethodAddr(void) 8 | { 9 | } 10 | -------------------------------------------------------------------------------- /src/parser/Declaration.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | #include "Declaration.h" 3 | 4 | IDeclaration::IDeclaration(void) 5 | { 6 | } 7 | 8 | IDeclaration::~IDeclaration(void) 9 | { 10 | } 11 | -------------------------------------------------------------------------------- /pbsrc/Samples/SetWindowHook/update.cmd: -------------------------------------------------------------------------------- 1 | set root=..\..\.. 2 | set vcdir=%root%\projects\libPBInvoke_vc8 3 | set pbdir=..\.. 4 | 5 | 6 | copy %vcdir%\ReleaseDemo\libPBInvoke.dll /y 7 | copy %pbdir%\PbInvoke\PbInvoke.pbl /y -------------------------------------------------------------------------------- /pbsrc/Samples/enumwindows/enumwindows.pbt: -------------------------------------------------------------------------------- 1 | Save Format v3.0(19990112) 2 | @begin Projects 3 | @end; 4 | appname "enumwindowsapp"; 5 | applib "enumwindows.pbl"; 6 | LibList "enumwindows.pbl;pbinvoke.pbl"; 7 | type "pb"; 8 | -------------------------------------------------------------------------------- /pbsrc/Samples/enumwindows/update.cmd: -------------------------------------------------------------------------------- 1 | set root=..\..\.. 2 | set vcdir=%root%\projects\libPBInvoke_vc8 3 | set pbdir=..\.. 4 | 5 | 6 | copy %vcdir%\ReleaseDemo\libPBInvoke.dll /y 7 | copy %pbdir%\PbInvoke\PbInvoke.pbl /y -------------------------------------------------------------------------------- /pbsrc/pbinvoke/build_pbinvoke.pbt: -------------------------------------------------------------------------------- 1 | Save Format v3.0(19990112) 2 | @begin Projects 3 | @end; 4 | appname "build_pbinvoke"; 5 | applib "build_pbinvoke.pbl"; 6 | LibList "build_pbinvoke.pbl;pbinvoke.pbl"; 7 | type "pb"; 8 | -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/update.cmd: -------------------------------------------------------------------------------- 1 | set root=..\..\.. 2 | set vcdir=%root%\projects\libPBInvoke_vc8 3 | set pbdir=..\.. 4 | 5 | 6 | copy %vcdir%\ReleaseDemo\libPBInvoke.dll /y 7 | copy %pbdir%\PbInvoke\PbInvoke.pbl /y -------------------------------------------------------------------------------- /pbsrc/tester.pbt: -------------------------------------------------------------------------------- 1 | Save Format v3.0(19990112) 2 | @begin Projects 3 | @end; 4 | appname "a_tester"; 5 | applib "tester\\tester.pbl"; 6 | LibList "tester\\tester.pbl;pbinvoke\\pbinvoke.pbl;tester\\debug.pbl"; 7 | type "pb"; 8 | -------------------------------------------------------------------------------- /src/types/BoolType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RawType.h" 4 | 5 | class BoolType: public RawType { 6 | public: 7 | BoolType() : RawType("bool", sizeof(bool)) {} 8 | virtual int getPBTypeClass() { return TC_BOOL_TYPE; } 9 | }; 10 | -------------------------------------------------------------------------------- /src/types/VoidType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RawType.h" 4 | 5 | class VoidType: public RawType { 6 | public: 7 | VoidType() : RawType("void", sizeof(char)) {} 8 | virtual int getPBTypeClass() { return TC_VOID_TYPE; } 9 | }; 10 | -------------------------------------------------------------------------------- /doc/help.hhk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /src/types/RefType.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | 3 | #include "RefType.h" 4 | 5 | #include "../PBException.h" 6 | 7 | RefType::RefType(Type &dataType) 8 | : PointerType(dataType, "&") 9 | { 10 | 11 | } 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/types/RefType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerType.h" 4 | 5 | class RefType : public PointerType 6 | { 7 | public: 8 | RefType(Type &dataType); 9 | virtual int getPBTypeClass() { return TC_REF_TYPE; } 10 | }; 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/types/ShortType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RawType.h" 4 | 5 | class ShortType: public RawType { 6 | public: 7 | ShortType() : RawType("short", sizeof(short)) {} 8 | virtual int getPBTypeClass() { return TC_SHORT_TYPE; } 9 | }; 10 | -------------------------------------------------------------------------------- /doc/genhelp/help.hhk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /pbsrc/Samples/SetWindowHook/setwindowshookdemo.pbt: -------------------------------------------------------------------------------- 1 | Save Format v3.0(19990112) 2 | @begin Projects 3 | @end; 4 | appname "setwindowshookdemo"; 5 | applib "setwindowshookdemo.pbl"; 6 | LibList "setwindowshookdemo.pbl;customsaveas.pbl;pbinvoke.pbl"; 7 | type "pb"; 8 | -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/browseforfolder.pbt: -------------------------------------------------------------------------------- 1 | Save Format v3.0(19990112) 2 | @begin Projects 3 | @end; 4 | appname "browseforfolder"; 5 | applib "browseforfolder_demo.pbl"; 6 | LibList "browseforfolder_demo.pbl;pbinvoke.pbl;browseforfolder.pbl"; 7 | type "pb"; 8 | -------------------------------------------------------------------------------- /projects/tester1/tester1.cpp: -------------------------------------------------------------------------------- 1 | // tester1.cpp : Defines the entry point for the console application. 2 | // 3 | 4 | #include "stdafx.h" 5 | 6 | __declspec(dllimport) void debug(); 7 | 8 | int _tmain(int argc, _TCHAR* argv[]) 9 | { 10 | debug(); 11 | return 0; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/readme.txt: -------------------------------------------------------------------------------- 1 | Setting starting directory in the "Browse For Folder" dialog. 2 | 3 | This sample demonstrates working with PB callbacks. 4 | 5 | See http://support.microsoft.com/kb/179378 for details. 6 | 7 | Before running the sample you need to migrate and full build it. 8 | -------------------------------------------------------------------------------- /src/parser/Declaration.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class IDeclaration 6 | { 7 | public: 8 | IDeclaration(void); 9 | virtual ~IDeclaration(void); 10 | }; 11 | 12 | typedef boost::shared_ptr Declaration; 13 | typedef vector Declarations; 14 | 15 | -------------------------------------------------------------------------------- /src/StdAfx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // libPBInvoke.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /src/parser/PrototypeDeclaration.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | #include "PrototypeDeclaration.h" 3 | 4 | PrototypeDeclaration::PrototypeDeclaration(void) 5 | : m_name("") 6 | , m_isStdCall(false) 7 | , m_align(0) 8 | { 9 | 10 | } 11 | 12 | PrototypeDeclaration::~PrototypeDeclaration(void) 13 | { 14 | } 15 | 16 | -------------------------------------------------------------------------------- /projects/libPBInvoke_vc9/postbuild.cmd: -------------------------------------------------------------------------------- 1 | rem echo on 2 | rem echo %* 3 | if "%OUTDIR%"=="" set OUTDIR=%1&& shift 4 | if "%OUTDIR%"=="" echo OUTDIR was not specified && exit 1 5 | 6 | set cfg=%1&& shift 7 | 8 | rem if "%cfg%"=="ReleaseDemo" exit /b 0 9 | 10 | set todir=..\..\pbsrc\tester 11 | 12 | copy %outdir%\*.dll %todir%\*.* /y -------------------------------------------------------------------------------- /projects/tester1/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // tester1.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /src/MethodInstance.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include "types/MethodType.h" 5 | 6 | class Method; 7 | class MethodInstance 8 | { 9 | public: 10 | virtual ~MethodInstance() {} 11 | virtual DWORD getMethodAddr() = 0; 12 | virtual MethodType* getMethodType() = 0; 13 | 14 | //virtual void invoke(Method *methodContext); 15 | }; 16 | -------------------------------------------------------------------------------- /src/PBException.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "PBException.h" 4 | 5 | PBExceptionStorage* PBExceptionStorage::m_instance = NULL; 6 | 7 | PBExceptionStorage& PBExceptionStorage::getInstance() 8 | { 9 | if (m_instance == NULL) { 10 | m_instance = new PBExceptionStorage(); 11 | } 12 | return *m_instance; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/PBException.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Runtime.h" 4 | 5 | class PBExceptionStorage: public ExecutionContext { 6 | public: 7 | static PBExceptionStorage& getInstance(); 8 | private: 9 | PBExceptionStorage() {} 10 | static PBExceptionStorage * m_instance; 11 | }; 12 | 13 | 14 | #define PBExceptionStorageInstance PBExceptionStorage::getInstance() 15 | -------------------------------------------------------------------------------- /src/parser/build_lexer.cmd: -------------------------------------------------------------------------------- 1 | pushd %~dp0 2 | set name=CLexer 3 | set ext=l 4 | perl -e "exit(((-M '%name%.%ext%' < -M '%name%.cpp') or !-f '%name%.cpp') ? 1 : 0)" 5 | @echo need rebuild=%errorlevel% 6 | if not errorlevel 1 goto _skip 7 | @echo compile L ... 8 | C:\Usr\App\Git\bin\flex.exe %name%.%ext% 9 | if errorlevel 1 exit %errorlevel% 10 | 11 | :_skip 12 | popd 13 | -------------------------------------------------------------------------------- /src/types/ArrayType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerType.h" 4 | 5 | class ArrayType : public PointerType 6 | { 7 | public: 8 | ArrayType(Type &dataType, size_t bound); 9 | virtual int getPBTypeClass() { return TC_ARRAY_TYPE; } 10 | virtual int getAlign() { return m_dataType->getAlign(); } 11 | protected: 12 | size_t m_bound; 13 | 14 | }; 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Objects/Structure.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Runtime.h" 4 | #include "../types/StructType.h" 5 | 6 | class ParamStorage; 7 | 8 | //TODO remove this class, value objects' func-ty is implemented in ExecutionContext 9 | class Structure : public ParamStorage 10 | { 11 | public: 12 | Structure(StructType *structType); 13 | virtual ~Structure(); 14 | 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /pbsrc/w.pbw: -------------------------------------------------------------------------------- 1 | Save Format v3.0(19990112) 2 | @begin Unchecked 3 | @end; 4 | @begin Targets 5 | 0 "tester.pbt"; 6 | 1 "Samples\\SetWindowHook\\setwindowshookdemo.pbt"; 7 | 2 "Samples\\BrowseForFolder\\browseforfolder.pbt"; 8 | 3 "pbinvoke\\build_pbinvoke.pbt"; 9 | 4 "Samples\\enumwindows\\enumwindows.pbt"; 10 | @end; 11 | DefaultTarget "tester.pbt"; 12 | DefaultRemoteTarget "tester.pbt"; 13 | -------------------------------------------------------------------------------- /src/types/Int64Type.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RawType.h" 4 | 5 | class Int64Type: public RawType { 6 | public: 7 | Int64Type() : RawType("__int64", sizeof(__int64)) {} 8 | virtual int getPBTypeClass() { return TC_LONGLONG_TYPE; } 9 | virtual void executeMethod(ExecutionContext *context, DWORD methodAddr, BYTE * retBuf, BYTE *paramBuf, int paramBufSize, bool isStdCall); 10 | }; 11 | -------------------------------------------------------------------------------- /src/types/DoubleType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RawType.h" 4 | 5 | class DoubleType: public RawType { 6 | public: 7 | DoubleType() : RawType("double", sizeof(double)) {} 8 | virtual int getPBTypeClass() { return TC_DOUBLE_TYPE; } 9 | virtual void executeMethod(ExecutionContext *context, DWORD methodAddr, BYTE * retBuf, BYTE *paramBuf, int paramBufSize, bool isStdCall); 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /src/types/FloatType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RawType.h" 4 | 5 | class FloatType: public RawType { 6 | public: 7 | FloatType() : RawType("float", sizeof(float)) {} 8 | virtual int getPBTypeClass() { return TC_FLOAT_TYPE; } 9 | virtual void executeMethod(ExecutionContext *context, DWORD methodAddr, BYTE * retBuf, BYTE *paramBuf, int paramBufSize, bool isStdCall); 10 | }; 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/types/TypeFactory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BaseType.h" 4 | 5 | 6 | class TypeFactory { 7 | private: 8 | static TypeFactory * m_instance; 9 | TypeFactory() {} 10 | TypeFactory(TypeFactory&) {} 11 | TypeFactory& operator=(TypeFactory&) {} 12 | public: 13 | static TypeFactory& getInstance(); 14 | Type createType(const string &typeName); 15 | Type createMethodType(const char* methodDecl); 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /src/types/FloatType.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | 3 | #include "FloatType.h" 4 | #include "../DynCallback.h" 5 | 6 | 7 | void FloatType::executeMethod(ExecutionContext *context, DWORD methodAddr, BYTE * retBuf, BYTE *paramBuf, int paramBufSize, bool isStdCall) 8 | { 9 | DWORD *argv = (DWORD *)paramBuf; 10 | int argc = paramBufSize / sizeof(DWORD); 11 | *(float*)retBuf = runDynamicFloatMethod(methodAddr, argv, argc, isStdCall); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/types/Int64Type.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | 3 | #include "Int64Type.h" 4 | #include "../DynCallback.h" 5 | 6 | 7 | 8 | void Int64Type::executeMethod(ExecutionContext *context, DWORD methodAddr, BYTE * retBuf, BYTE *paramBuf, int paramBufSize, bool isStdCall) 9 | { 10 | DWORD *argv = (DWORD *)paramBuf; 11 | int argc = paramBufSize / sizeof(DWORD); 12 | *(__int64*)retBuf = runDynamicInt64Method(methodAddr, argv, argc, isStdCall); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/types/DoubleType.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | 3 | #include "DoubleType.h" 4 | #include "../DynCallback.h" 5 | 6 | 7 | 8 | void DoubleType::executeMethod(ExecutionContext *context, DWORD methodAddr, BYTE * retBuf, BYTE *paramBuf, int paramBufSize, bool isStdCall) 9 | { 10 | DWORD *argv = (DWORD *)paramBuf; 11 | int argc = paramBufSize / sizeof(DWORD); 12 | *(double*)retBuf = runDynamicDoubleMethod(methodAddr, argv, argc, isStdCall); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/types/IntType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RawType.h" 4 | 5 | class IntType: public RawType { 6 | public: 7 | IntType() : RawType("int", sizeof(int)) {} 8 | virtual int getPBTypeClass() { return TC_INT_TYPE; } 9 | }; 10 | 11 | class THandleType: public RawType { 12 | public: 13 | THandleType() : RawType("__thandle", sizeof(int)) {} 14 | virtual int getPBTypeClass() { return TC_INT_TYPE; } 15 | virtual bool hasTChar() { return true; } 16 | }; 17 | -------------------------------------------------------------------------------- /src/types/ArrayType.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | 3 | #include "ArrayType.h" 4 | 5 | #include "../PBException.h" 6 | 7 | ArrayType::ArrayType(Type &dataType, size_t bound) 8 | : PointerType(dataType, "[" + string(CUtil::toString(bound)) + "]", dataType->getSizeOf() * bound) 9 | , m_bound(bound) 10 | { 11 | //if (m_bound == 0) 12 | // throw RuntimeException("Internal error: ArrayType::ArrayType expect non-zero array bound"); 13 | } 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Developer Studio generated include file. 3 | // Used by version.rc 4 | // 5 | 6 | // Next default values for new objects 7 | // 8 | #ifdef APSTUDIO_INVOKED 9 | #ifndef APSTUDIO_READONLY_SYMBOLS 10 | #define _APS_NEXT_RESOURCE_VALUE 101 11 | #define _APS_NEXT_COMMAND_VALUE 40001 12 | #define _APS_NEXT_CONTROL_VALUE 1000 13 | #define _APS_NEXT_SYMED_VALUE 101 14 | #endif 15 | #endif 16 | -------------------------------------------------------------------------------- /src/WinHooks.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "WinHooks.h" 3 | 4 | 5 | bool IWinHookHelper::skip(HHOOK hhk, PHookProcArgs args, vector&messageFilter, LRESULT &result) 6 | { 7 | if (args->nCode >= 0) { 8 | UINT& message = getMessage(args); 9 | for (size_t i = 0; i < messageFilter.size(); i ++) { 10 | if (messageFilter[i] == message) 11 | return false; 12 | } 13 | } 14 | result = CallNextHookEx(hhk, args->nCode, args->wParam, args->lParam); 15 | return true; 16 | } 17 | -------------------------------------------------------------------------------- /src/types/DataTypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #include "StringType.h" 5 | #include "MethodType.h" 6 | #include "BoolType.h" 7 | #include "IntType.h" 8 | #include "DoubleType.h" 9 | #include "FloatType.h" 10 | #include "StructType.h" 11 | #include "PointerType.h" 12 | #include "RefType.h" 13 | #include "CharType.h" 14 | #include "Int64Type.h" 15 | #include "VoidType.h" 16 | #include "ShortType.h" 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/types/PointerType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RawType.h" 4 | 5 | class PointerType : public RawType 6 | { 7 | public: 8 | PointerType(Type &dataType, const string& ptrSig = "*", size_t sizeOf = sizeof(BYTE*)); 9 | virtual int getPBTypeClass() { return TC_PTR_TYPE; } 10 | Type& getDataType() { return m_dataType; } 11 | virtual bool hasTChar() { dprintf("PointerType->hasTChar=%i\n", m_dataType->hasTChar()); return m_dataType->hasTChar(); } 12 | protected: 13 | Type m_dataType; 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /src/parser/PrototypeDeclaration.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Declaration.h" 3 | #include "../types/BaseType.h" 4 | 5 | 6 | class PrototypeDeclaration: public IDeclaration 7 | { 8 | public: 9 | PrototypeDeclaration(); 10 | ~PrototypeDeclaration(void); 11 | 12 | string m_name; 13 | size_t m_align; 14 | bool m_isStdCall; 15 | vector m_paramTypes; 16 | Type m_returnType; 17 | }; 18 | 19 | inline PrototypeDeclaration* proto(Declaration &decl) 20 | { 21 | return (PrototypeDeclaration*) decl.get(); 22 | } -------------------------------------------------------------------------------- /src/DLLMethodInstance.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MethodInstance.h" 3 | 4 | class Library; 5 | 6 | class DLLMethodInstance: public MethodInstance 7 | { 8 | private: 9 | Library *m_library; 10 | string m_methodName; 11 | DWORD m_methodAddr; 12 | MethodType* m_methodType; 13 | public: 14 | DLLMethodInstance(Library *library, const string &methodName, MethodType* methodType); 15 | virtual ~DLLMethodInstance(); 16 | 17 | // iface MethodInstance 18 | virtual DWORD getMethodAddr(); 19 | virtual MethodType* getMethodType(); 20 | }; 21 | -------------------------------------------------------------------------------- /pbsrc/pbinvoke/default.pbc: -------------------------------------------------------------------------------- 1 | Version = 1 2 | PbVersion = 9 3 | SrcDir = 4 | 5 | App = build_pbinvoke 6 | Libs = ( 7 | build_pbinvoke.pbl,,1 8 | pbinvoke.pbl,,1 9 | ) 10 | Exe = # Executable file name 11 | ExePbr = 12 | ExeIcon = 13 | MachineCode = 0 # 0 - P-CODE, 1 - DLL 14 | #Use new visual style controls (XP) 15 | xpstyle = 0 # 0 - old / 1 - new 16 | 17 | ProductName = 18 | CompanyName = 19 | Description = 20 | Copyright = 21 | ProductVersion = 22 | ProductVersionNum = 23 | FileVersion = 24 | FileVersionNum = 25 | 26 | -------------------------------------------------------------------------------- /pbsrc/Samples/SetWindowHook/readme.txt: -------------------------------------------------------------------------------- 1 | Setting file type filter in the "Save As" dialog. 2 | 3 | This sample demonstrates working with structures, PB callbacks and callback message filters. 4 | 5 | The sample is based on SetWindowsHookEx sample from Codexchange. 6 | http://downloads.sybase.com/codexchange/powerbuilder/454/PBNISetWindowHook.zip 7 | 8 | The PowerScript part of the original sample was not changed. 9 | The PBNI(C++) part was re-written in PowerScript using PBInvoke. 10 | 11 | 12 | Before running the sample you need to migrate and full build it. 13 | -------------------------------------------------------------------------------- /src/WinHooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | //using namespace 4 | #pragma pack(push, 4) 5 | typedef struct HookProcArgs { 6 | int nCode; 7 | WPARAM wParam; 8 | LPARAM lParam; 9 | } HookProcArgs, *PHookProcArgs ; 10 | #pragma pack(pop) 11 | 12 | struct IWinHookHelper { 13 | virtual UINT& getMessage(PHookProcArgs args) = 0; 14 | virtual ~IWinHookHelper() {} 15 | bool skip(HHOOK hhk, PHookProcArgs args, vector&messageFilter, LRESULT &result); 16 | }; 17 | 18 | typedef boost::shared_ptr WinHookHelper; 19 | -------------------------------------------------------------------------------- /projects/tester1/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. 9 | #define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. 10 | #endif 11 | 12 | #include 13 | #include 14 | 15 | 16 | 17 | // TODO: reference additional headers your program requires here 18 | -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/default.pbc: -------------------------------------------------------------------------------- 1 | Version = 1 2 | PbVersion = 9 3 | SrcDir = 4 | 5 | App = 6 | Libs = ( 7 | browseforfolder_demo.pbl,,1 8 | browseforfolder.pbl,,1 9 | pbinvoke.pbl,,1 10 | ) 11 | Exe = Debug\aaaaa.exe # Executable file name 12 | ExePbr = 13 | ExeIcon = 14 | MachineCode = 0 # 0 - P-CODE, 1 - DLL 15 | #Use new visual style controls (XP) 16 | xpstyle = 0 # 0 - old / 1 - new 17 | 18 | ProductName = 19 | CompanyName = 20 | Description = 21 | Copyright = 22 | ProductVersion = 23 | ProductVersionNum = 24 | FileVersion = 25 | FileVersionNum = 26 | 27 | -------------------------------------------------------------------------------- /pbsrc/Samples/SetWindowHook/default.pbc: -------------------------------------------------------------------------------- 1 | Version = 1 2 | PbVersion = 9 3 | SrcDir = 4 | 5 | App = setwindowshookdemo 6 | Libs = ( 7 | setwindowshookdemo.pbl,,1 8 | customsaveas.pbl,,1 9 | pbinvoke.pbl,,1 10 | ) 11 | Exe = # Executable file name 12 | ExePbr = 13 | ExeIcon = 14 | MachineCode = 0 # 0 - P-CODE, 1 - DLL 15 | #Use new visual style controls (XP) 16 | xpstyle = 0 # 0 - old / 1 - new 17 | 18 | ProductName = 19 | CompanyName = 20 | Description = 21 | Copyright = 22 | ProductVersion = 23 | ProductVersionNum = 24 | FileVersion = 25 | FileVersionNum = 26 | 27 | -------------------------------------------------------------------------------- /doc/_template_help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | $TITLE 4 | 5 | 6 | 7 |
8 | 11 |
$CONTENT
12 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /pbsrc/default.pbc: -------------------------------------------------------------------------------- 1 | Version = 1 2 | PbVersion = 9 3 | SrcDir = 4 | 5 | App = a_tester 6 | Libs = ( 7 | tester\tester.pbl,,1 8 | pbinvoke\pbinvoke.pbl,,1 9 | tester\debug.pbl,,1 10 | ) 11 | Exe = ..\projects\libPBInvoke\Debug\aaaaa.exe # Executable file name 12 | ExePbr = 13 | ExeIcon = 14 | MachineCode = 0 # 0 - P-CODE, 1 - DLL 15 | #Use new visual style controls (XP) 16 | xpstyle = 0 # 0 - old / 1 - new 17 | 18 | ProductName = 19 | CompanyName = 20 | Description = 21 | Copyright = 22 | ProductVersion = 23 | ProductVersionNum = 24 | FileVersion = 25 | FileVersionNum = 26 | 27 | -------------------------------------------------------------------------------- /src/parser/build_parser.cmd: -------------------------------------------------------------------------------- 1 | @pushd %~dp0 2 | @set path=C:\Usr\App\GnuWin32\bin;%path% 3 | @set name=CParser 4 | @set ext=y 5 | @set BISON_PKGDATADIR=C:\Usr\App\GnuWin32\share\bison 6 | @if "%1"=="1" del /q %name%.cpp 7 | 8 | @perl -e "exit(((-M '%name%.%ext%' < -M '%name%.cpp') or !-f '%name%.cpp') ? 1 : 0)" 9 | @echo need rebuild=%errorlevel% 10 | @if not errorlevel 1 goto _skip 11 | @echo compile Y ... 12 | if exist %name%.cpp del /q %name%.cpp 13 | bison.exe --report=all --no-lines CParser.y 14 | if errorlevel 1 exit %errorlevel% 15 | move /y CParser.tab.c CParser.cpp 16 | if errorlevel 1 exit %errorlevel% 17 | 18 | :_skip 19 | @popd 20 | -------------------------------------------------------------------------------- /src/parser/CParser.hlp.h: -------------------------------------------------------------------------------- 1 | //#pragma message("inlude CParser.hlp.h") 2 | #pragma once 3 | #pragma warning (disable:4065) 4 | #include "../stdafx.h" 5 | #include "../types/BaseType.h" 6 | #include "../Compiler.h" 7 | #include "../Core.h" 8 | #include "ASTNode.h" 9 | 10 | //#include 11 | //#include 12 | 13 | using namespace std; 14 | 15 | struct YYSTYPE { 16 | string text; 17 | Type type; 18 | ASTNode node; 19 | vector items; 20 | NamedType namedType; 21 | int ival; 22 | }; 23 | #define YYSTYPE_IS_DECLARED 1 24 | 25 | //#define yylex CLexerlex 26 | int yylex(YYSTYPE* yylval); 27 | 28 | //class Compiler; 29 | -------------------------------------------------------------------------------- /doc/help.hhp: -------------------------------------------------------------------------------- 1 | [OPTIONS] 2 | Compatibility=1.1 or later 3 | Compiled file=..\pbinvoke_en.chm 4 | Contents file=help.hhc 5 | Default topic=index.html 6 | Display compile progress=No 7 | Full-text search=Yes 8 | Index file=help.hhk 9 | Language=0x409 English (United States) 10 | Title=PBInvoke Documentation 11 | 12 | 13 | [FILES] 14 | calling-dll-functions.html 15 | handling-strings.html 16 | handling-tchar.html 17 | index.html 18 | license.html 19 | quick-start-guide.html 20 | style.css 21 | supported-data-types.html 22 | unsupported.html 23 | winapi.html 24 | working-with-callbacks.html 25 | working-with-structures.html 26 | 27 | [INFOTYPES] 28 | 29 | -------------------------------------------------------------------------------- /doc/genhelp/help.hhp: -------------------------------------------------------------------------------- 1 | [OPTIONS] 2 | Compatibility=1.1 or later 3 | Compiled file=..\pbinvoke_en.chm 4 | Contents file=help.hhc 5 | Default topic=index.html 6 | Display compile progress=No 7 | Full-text search=Yes 8 | Index file=help.hhk 9 | Language=0x409 English (United States) 10 | Title=PBInvoke Documentation 11 | 12 | 13 | [FILES] 14 | calling-dll-functions.html 15 | handling-strings.html 16 | handling-tchar.html 17 | index.html 18 | license.html 19 | quick-start-guide.html 20 | style.css 21 | supported-data-types.html 22 | unsupported.html 23 | winapi.html 24 | working-with-callbacks.html 25 | working-with-structures.html 26 | 27 | [INFOTYPES] 28 | 29 | -------------------------------------------------------------------------------- /doc/_template_site.html: -------------------------------------------------------------------------------- 1 | <% 2 | my $parent = $page->reuse ('..'); 3 | $$page{TITLE} = '$TITLE'; 4 | $$page{DIRTITLE} = '$TITLE'; 5 | push @{$$page{KEYWORDS}}, qw(PBInvoke PowerBuilder DLL union C C++ callbacks); 6 | $$page{STYLE} = "/t/style/style.css"; 7 | %> 8 | 9 | <%$page->include('/t/header.html')%> 10 | 11 | $CONTENT 12 | 13 | 14 | <% 15 | $$page{LINKS} = 16 | [ 17 | [ 18 | 'PBInvoke', 19 | [ 20 | ['index.html', 'Home'], 21 | ['download.html', 'Download Demo'], 22 | ['doc.html', 'Documentation'], 23 | ['purchase.html', 'Purchase'], 24 | ], 25 | ], 26 | $SEEALSO 27 | ]; 28 | 29 | %> 30 | 31 | <%$page->include('/t/footer.html')%> 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/types/PointerType.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | 3 | #include "PointerType.h" 4 | 5 | #include "../PBException.h" 6 | 7 | PointerType::PointerType(Type &dataType, const string& ptrSig, size_t sizeOf) 8 | : RawType(dataType->getTypeSignature(ptrSig), sizeOf) 9 | , m_dataType(dataType) 10 | { 11 | dprintf("PointerType, type=%p, sig=%s\n", dataType.get(), dataType->getTypeSignature("*").c_str()); 12 | } 13 | 14 | 15 | BOOL PBCALL pt_getMetaData(PointerType* ptrType, BaseType* &dataType, int &dataTypeClass) 16 | { 17 | PBExceptionStorageInstance.clearLastExceptionMessage(); 18 | try { 19 | dataType = ptrType->getDataType().get(); 20 | if (dataType != NULL) 21 | dataTypeClass = dataType->getPBTypeClass(); 22 | return true; 23 | } 24 | catch (...) { 25 | } 26 | return false; 27 | } 28 | -------------------------------------------------------------------------------- /src/DLLMethodInstance.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | 3 | #include "DLLMethodInstance.h" 4 | #include "Runtime.h" 5 | #include "PBException.h" 6 | 7 | DLLMethodInstance::DLLMethodInstance(Library *library, const string &methodName, MethodType* methodType) 8 | : m_library(library) 9 | , m_methodName(methodName) 10 | , m_methodAddr(0) 11 | , m_methodType(methodType) 12 | { 13 | dprintf("DLLMethodInstance::DLLMethodInstance\n"); 14 | getMethodAddr(); // throws if method does not exist 15 | } 16 | 17 | DWORD DLLMethodInstance::getMethodAddr() 18 | { 19 | if (m_methodAddr == 0) { 20 | m_methodAddr = m_library->getMethodAddr(m_methodName); 21 | } 22 | return m_methodAddr; 23 | } 24 | 25 | DLLMethodInstance::~DLLMethodInstance() 26 | { 27 | dprintf("DLLMethodInstance::~DLLMethodInstance\n"); 28 | } 29 | 30 | MethodType* DLLMethodInstance::getMethodType() 31 | { 32 | return m_methodType; 33 | } 34 | -------------------------------------------------------------------------------- /src/Objects/Structure.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | 3 | #include "Structure.h" 4 | #include "../PBException.h" 5 | 6 | Structure::Structure(StructType *structType) 7 | : ParamStorage(structType->getItems()) 8 | { 9 | 10 | } 11 | 12 | Structure::~Structure() 13 | { 14 | 15 | } 16 | 17 | 18 | Structure * PBCALL str_create(StructType *structType) 19 | { 20 | PBExceptionStorageInstance.clearLastExceptionMessage(); 21 | try { 22 | return new Structure(structType); 23 | } 24 | catch (...) { 25 | return NULL; 26 | } 27 | } 28 | 29 | 30 | BOOL PBCALL str_getContextData(Structure *structure, BYTE* fieldAddr[], int fieldCount) 31 | { 32 | PBExceptionStorageInstance.clearLastExceptionMessage(); 33 | try { 34 | for (int i = 0; i < fieldCount; i ++) { 35 | fieldAddr[i] = structure->getParamAddr(i); 36 | } 37 | return true; 38 | } 39 | catch (...) { 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/parser/clexer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma warning (disable:4065) 3 | 4 | #include "CParser.tab.h" 5 | #include 6 | #include 7 | using namespace std; 8 | //namespace yy { 9 | //class CLexer: public yyFlexLexer { 10 | // public: 11 | // int yylex(YYSTYPE* yylval); 12 | //}; 13 | 14 | //} 15 | 16 | class CLexer { 17 | static istream* m_inputStream; 18 | istream* m_prevInputStream; 19 | istream* m_currInputStream; 20 | public: 21 | inline CLexer(istream* is /*caller must delete is*/); 22 | void pushInput(); 23 | void popInput(); 24 | static inline istream* in() {return m_inputStream; } 25 | inline ~CLexer(); 26 | }; 27 | 28 | inline CLexer::CLexer(istream* is) 29 | : m_currInputStream(is) 30 | , m_prevInputStream(NULL) 31 | { 32 | if (m_currInputStream == NULL) 33 | throw "m_currInputStream == NULL"; 34 | pushInput(); 35 | m_inputStream = m_currInputStream; 36 | } 37 | inline CLexer::~CLexer() 38 | { 39 | popInput(); 40 | } 41 | -------------------------------------------------------------------------------- /src/PBCallback.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DynCallback.h" 4 | #include "MethodInstance.h" 5 | #include "Runtime.h" 6 | 7 | #include 8 | 9 | 10 | 11 | class PBCallback : public MethodInstance, public CallbackData 12 | { 13 | protected: 14 | MethodType *m_methodType; 15 | UINT m_callbackId; 16 | int m_inCall; 17 | Method *m_currentContext; 18 | stack m_contexts; 19 | vector m_messageFilter; 20 | HHOOK m_hhk; 21 | int m_hookId; 22 | bool m_enable; 23 | public: 24 | PBCallback(UINT callbackId, Method *defaultMethodContext); 25 | virtual ~PBCallback(); 26 | void createCallbackContext(BYTE *argsPtr); 27 | void destroyCallbackContext(); 28 | 29 | void setHookFilter(HHOOK hhk, int hookId, UINT messageFilter[], size_t messageFilterSize); 30 | 31 | // iface CallbackData 32 | virtual int CALLBACK callback(); 33 | 34 | // iface MethodInstance 35 | virtual DWORD getMethodAddr(); 36 | virtual MethodType* getMethodType() { return m_methodType; } 37 | 38 | }; 39 | 40 | -------------------------------------------------------------------------------- /doc/doc.html: -------------------------------------------------------------------------------- 1 |

PBInvoke library documetation

2 | 3 | 4 | 5 |

Table of contents

6 | General 7 | 11 | Reference 12 | 19 | Advanced 20 | 24 | 25 | Misc 26 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/types/StringType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerType.h" 4 | 5 | //class StringType: public PointerType { 6 | //protected: 7 | // StringType(const string &typeSignature); 8 | //public: 9 | // virtual int getPBTypeClass(); 10 | // //inline void setPBUnicode(bool isPBUnicode) { m_isPBUnicode = isPBUnicode;} 11 | //protected: 12 | // //bool m_isPBUnicode; 13 | //}; 14 | // 15 | //class AStringType: public StringType { 16 | //public: 17 | // AStringType() : StringType("char*") {} 18 | // virtual void setStringData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int strLen, DataCharset charset); 19 | // virtual void getStringData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int &strLen, DataCharset charset); 20 | //}; 21 | //class WStringType: public StringType { 22 | //public: 23 | // WStringType() : StringType("wchar_t*") {} 24 | // virtual void setStringData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int strLen, DataCharset charset); 25 | // virtual void getStringData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int &strLen, DataCharset charset); 26 | //}; 27 | -------------------------------------------------------------------------------- /src/Compiler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "parser/Declaration.h" 4 | //#include "types/StructType.h" 5 | #include 6 | using namespace stdext; 7 | class Compiler 8 | { 9 | private: 10 | Declarations m_declarations; 11 | string m_errorMessage; 12 | const string m_nameSpace; 13 | vector m_typeDefs; 14 | vector m_names; 15 | hash_map m_tags; 16 | bool m_enableTCharSuffix; 17 | 18 | public: 19 | Compiler(const string &nameSpace = "", bool enableTCharSuffix = true); 20 | virtual ~Compiler(); 21 | /** @return name of the last name def or "" */ 22 | string compileAsC(const char* source); 23 | string compileAsCTypedef(const string &source); 24 | inline Declarations& getDeclarations() { return m_declarations; } 25 | inline void addDeclaration(Declaration& decl) { m_declarations.push_back(decl); } 26 | inline void setErrorMessage(const string& message) { m_errorMessage = message; } 27 | Type findType(const string& typeName, bool throwNotFound = true); 28 | Type defineType(const string& typeName, Type &typeRef); 29 | Type defineName(string name, Type &typeRef); 30 | Type defineTag(const string& typeName, Type &typeRef); 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /src/MethodInstance.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | 3 | #include "MethodInstance.h" 4 | #include "Runtime.h" 5 | #include "PBException.h" 6 | 7 | //typedef struct __declspec(align(16)) S {int a;} S; 8 | //typedef enum U { AA } U; 9 | //int U(); 10 | 11 | void PBCALL mi_destroy(MethodInstance *methodInstance) 12 | { 13 | PBExceptionStorageInstance.clearLastExceptionMessage(); 14 | try { 15 | dprintf("mi_destroy methodInstance=%p\n", methodInstance); 16 | if (methodInstance != NULL) 17 | delete methodInstance; 18 | dprintf("mi_destroy OK\n"); 19 | } 20 | catch(...) { 21 | dprintf("mi_destroy failed\n"); 22 | } 23 | } 24 | 25 | DWORD PBCALL mi_getMethodAddr(MethodInstance* methodInstance) 26 | { 27 | PBExceptionStorageInstance.clearLastExceptionMessage(); 28 | try { 29 | if (methodInstance != NULL) 30 | return methodInstance->getMethodAddr(); 31 | } 32 | catch(...) { 33 | } 34 | return NULL; 35 | } 36 | 37 | MethodType* PBCALL mi_getMethodType(MethodInstance* methodInstance) 38 | { 39 | PBExceptionStorageInstance.clearLastExceptionMessage(); 40 | try { 41 | if (methodInstance != NULL) 42 | return methodInstance->getMethodType(); 43 | } 44 | catch(...) { 45 | } 46 | return NULL; 47 | } 48 | -------------------------------------------------------------------------------- /doc/unsupported.html: -------------------------------------------------------------------------------- 1 |

Unsupported and unimplemented PBInvoke features

2 | 3 | 4 |

Unsupported usage of PBInvoke

5 | The following modes may (or may not) work but are not supported officially. 6 |
  • Using PBInvoke with PowerBuilder 5 (PBInvoke supports only PB 6 and above) 7 |
  • Machine code targets (DLL builds) 8 |
  • Web and .Net targets (WinForm, WebForm, JSP, Web services ...) 9 | 10 |

    Only P-code (PBD) builds are supported. 11 | 12 |

    Unimplemented features

    13 | 14 | The following features will be implemented in one of the future versions of PBInvoke. 15 | 16 |
  • .Net interop (calls to external .Net classes, not under .Net targets) 17 |
  • Java interop (calls to external Java classes) 18 |
  • Calls via function pointers (now only named DLL functions and PB callbacks can be called) 19 |
  • Double, float as a return type for callbacks. However pointers to such types are supported as a return type. 20 |
  • Any struct of size of more than 4 bytes as a return type for any function. 21 | However pointers to such structures are supported as a return type. 22 |
  • C++ classes, structures inherited from other structures. 23 | 24 |

    See also

    25 |
  • Supported data types 26 |
  • WinAPI constants and types 27 | 28 | -------------------------------------------------------------------------------- /doc/winapi.html: -------------------------------------------------------------------------------- 1 |

    WinAPI constants and types

    2 | 3 |

    WinAPI is most widely used as external functions in PowerBuilder. 4 | 5 |

    WinAPI constants

    6 |

    PBInvoke provides an object with many WinAPI constants, n_pi_winapi. 7 | The constants can be used without instantiation of the object via syntax: 8 | 9 | n_pi_winapi.CONSTANT_NAME 10 | 11 | 12 |

    Example: 13 | 14 | lnv_SendMessage.of_invoke(Handle(w_win), n_pi_winapi.WM_KEYDOWN, 9 /*Tab*/, 0) 15 | 16 | 17 | 18 |

    WinAPI types

    19 | 20 | PBInvoke has built-in support for the following WinAPI types: 21 |
    22 | TCHAR, TSTR, LPTSTR, LPCTSTR, WCHAR, WSTR, LPWSTR, LPCWSTR, CHAR, STR, LPSTR, LPCSTR, BYTE,BOOL, HWND, HINSTANCE, 23 | LPBOOL, INT, UINT, UINT_PTR, DWORD, LPDWORD, HANDLE, LRESULT, LONG, ULONG, WPARAM, LPARAM, HMODULE, HHOOK, 24 | WORD, LPWORD, SHORT, USHORT, VOID, PVOID, LPVOID, LPCVOID, FLOAT, LPSECURITY_ATTRIBUTES 25 |
    26 | 27 |

    See also

    28 |
  • Calling DLL functions using PBInvoke 29 |
  • Handling TCHAR and TSTR. Unicode/ANSI function name suffixes 30 |
  • Supported data types 31 |
  • Working with callbacks 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /doc/handling-tchar.html: -------------------------------------------------------------------------------- 1 |

    Handling TCHAR and TSTR. Unicode/ANSI function name suffixes

    2 |

    When at least one of parameter types or return type of a declared DLL function is based on TCHAR type, 3 | then PBInvoke automatically appends a suffix "A" or "W" to the function's name and treats TCHAR as char or wchar_t 4 | depending on PowerBuilder version. 5 |

    In Unicode versions (PB10 and above), the "W" suffix is appended and TCHAR=wchar_t, 6 |

    In ANSI version (PB9 and below) , the "A" suffix is appended and TCHAR=char. 7 | 8 |

    If the function with the suffix does not exist in the DLL, then PBInvoke tries to find the function without the prefix. 9 | 10 |

    Example: 11 | 12 | lnv_CreateDirectory = lnv_kernel32.of_declare_method(& 13 | "BOOL CreateDirectory(LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);") 14 | // The exact meaning of the declaration above depends on PB version: 15 | // in PB9: BOOL CreateDirectoryA(const char *lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes) 16 | // in PB10: BOOL CreateDirectoryW(const wchar_t *lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes) 17 | 18 | 19 |

    See also

    20 |
  • Handling strings (char*, wchar_t*) 21 |
  • WinAPI constants and types 22 |
  • Working with callbacks 23 | -------------------------------------------------------------------------------- /src/PBInvoke.def: -------------------------------------------------------------------------------- 1 | LIBRARY 2 | EXPORTS 3 | 4 | 5 | ;at_getMetaData 6 | 7 | bt_allocateBuffer 8 | bt_create 9 | bt_getArrayData 10 | bt_getData 11 | bt_getInt64 12 | bt_getItemIndex 13 | bt_getPBTypeClass 14 | bt_getPtr 15 | bt_getSizeOf 16 | bt_isCompatible 17 | bt_isSame 18 | bt_setData 19 | bt_setArrayData 20 | bt_setInt64 21 | ;bt_setPointerToArrayData 22 | bt_setPtr 23 | bt_setZeroData 24 | 25 | cb_create 26 | cb_destroy 27 | cb_getAddr 28 | cb_setHookFilter 29 | 30 | core_check 31 | core_compile 32 | core_getPack 33 | core_popPack 34 | core_pushPack 35 | core_setAppHandle 36 | core_setCallbackMessageId 37 | core_setCallbackMessageHandler 38 | core_setDefCallingConvention 39 | core_setKey 40 | core_setPack 41 | 42 | ctx_clear 43 | ctx_create 44 | ctx_destroy 45 | 46 | er_getLastException 47 | 48 | g_isPBUnicode 49 | g_getCoreInstance 50 | 51 | lib_create 52 | lib_createMethodInstance 53 | lib_destroy 54 | 55 | me_create 56 | me_destroy 57 | me_getContextData 58 | me_invoke 59 | 60 | mi_destroy 61 | mi_getMethodAddr 62 | mi_getMethodType 63 | 64 | mt_getMethodTypeData1 65 | mt_getMethodTypeData2 66 | 67 | pt_getMetaData 68 | 69 | ;rt_getMetaData 70 | 71 | s_destroy 72 | s_get 73 | s_size 74 | 75 | str_create 76 | str_getContextData 77 | str_getTypeData1 78 | str_getTypeData2 79 | 80 | tf_createMethodType 81 | 82 | debug 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /doc/gen_help.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use File::Misc; 3 | use File::Path; 4 | use File::Copy; 5 | 6 | my $templateFile = "_template_help.html"; 7 | my $outDir = "genhelp"; 8 | 9 | my $templateText = ReadFile($templateFile); 10 | 11 | my @files = sort (<*.*>, ); 12 | 13 | for my $file (@files) { 14 | if ($file =~ /template/i) { 15 | next; 16 | } 17 | elsif ($file =~ /\.html$/i) { 18 | genFile($file) ; 19 | } 20 | elsif ($file =~ /\.(css|png|gif|hh\w)$/i) { 21 | copyFile($file); 22 | } 23 | } 24 | 25 | sub copyFile { 26 | my ($file) = @_; 27 | print "Copying $file\n"; 28 | copy($file, "$outDir/$file"); 29 | } 30 | 31 | sub genFile { 32 | my ($file) = @_; 33 | print "Generating $file\n"; 34 | my $content = ReadFile($file) or die "$!: $file"; 35 | my ($title) = $content =~ m!

    (.*?)

    !is; 36 | $title ||= $file; 37 | my $text = $templateText; 38 | $text =~ s/\$CONTENT\b/$content/gs; 39 | $text =~ s/\$TITLE\b/$title/gs; 40 | 41 | # colorize 42 | $text =~ s!(\)(.*?)(\<\/pb\>)!'
    '. colorize($2). '
    '!gsie; 43 | 44 | # remove 1st empty line in
     
    45 | 	$text =~ s/(\]*\>)\s+/$1/gsi;
    46 | 
    47 | 	mkpath($outDir);
    48 | 	WriteFile("$outDir/$file", $text);
    49 | }
    50 | 
    51 | sub colorize {
    52 | 	my ($text) = @_;
    53 | 	$text =~ s!(//.*)$!$1!gm;
    54 | 	$text =~ s!(/\*.*?\*/)!$1!gms;
    55 | 	return $text;
    56 | }
    
    
    --------------------------------------------------------------------------------
    /projects/tester1/ReadMe.txt:
    --------------------------------------------------------------------------------
     1 | ========================================================================
     2 |     CONSOLE APPLICATION : tester1 Project Overview
     3 | ========================================================================
     4 | 
     5 | AppWizard has created this tester1 application for you.  
     6 | 
     7 | This file contains a summary of what you will find in each of the files that
     8 | make up your tester1 application.
     9 | 
    10 | 
    11 | tester1.vcproj
    12 |     This is the main project file for VC++ projects generated using an Application Wizard. 
    13 |     It contains information about the version of Visual C++ that generated the file, and 
    14 |     information about the platforms, configurations, and project features selected with the
    15 |     Application Wizard.
    16 | 
    17 | tester1.cpp
    18 |     This is the main application source file.
    19 | 
    20 | /////////////////////////////////////////////////////////////////////////////
    21 | Other standard files:
    22 | 
    23 | StdAfx.h, StdAfx.cpp
    24 |     These files are used to build a precompiled header (PCH) file
    25 |     named tester1.pch and a precompiled types file named StdAfx.obj.
    26 | 
    27 | /////////////////////////////////////////////////////////////////////////////
    28 | Other notes:
    29 | 
    30 | AppWizard uses "TODO:" comments to indicate parts of the source code you
    31 | should add to or customize.
    32 | 
    33 | /////////////////////////////////////////////////////////////////////////////
    34 | 
    
    
    --------------------------------------------------------------------------------
    /src/types/RawType.h:
    --------------------------------------------------------------------------------
     1 | 
     2 | #pragma once
     3 | 
     4 | #include "BaseType.h"
     5 | 
     6 | // Generic plain C type 
     7 | class RawType: public BaseType
     8 | {
     9 | private:
    10 | protected:
    11 | 	RawType(const string &typeSignature, size_t sizeOf = sizeof(DWORD));
    12 | 	size_t m_sizeOf;
    13 | 	string m_typeSignature;
    14 | 
    15 | 	void setSizeOf(size_t sizeOf) { m_sizeOf = sizeOf; }
    16 | public:
    17 | 	virtual int getSizeOf() { return m_sizeOf; }
    18 | 	//virtual void setData(ExecutionContext *context, BYTE * cBuf, BYTE * pbBuf);
    19 | 	//virtual void getData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf);
    20 | 	virtual void executeMethod(ExecutionContext *context, DWORD methodAddr, BYTE * retBuf, BYTE *paramBuf, int paramBufSize, bool isStdCall);
    21 | 	virtual int getItemOffset(int itemIndex) {return 0;}
    22 | 	virtual void allocateBuffer(ExecutionContext *context, BYTE * &buf, int itemCount = 1);
    23 | 	virtual string getTypeSignature(const string& pointerSig = "");
    24 | 	virtual void setZeroData(ExecutionContext *context, BYTE * buf);
    25 | 	virtual int getExplicitAlign() { return 0; }
    26 | 	virtual int getAlign() { return getSizeOf(); }
    27 | 	// unimplemented (throw)
    28 | 	virtual void getArrayData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int &arrayLen, DataCharset charset);
    29 | 	virtual void setArrayData(ExecutionContext *context, BYTE * &cBuf, BYTE *pbBuf, int arrayLen, DataCharset charset);
    30 | 	virtual size_t strLen(ExecutionContext *context, BYTE * buf, int arrayLen, DataCharset charset) { return 0;}
    31 | };
    32 | 
    
    
    --------------------------------------------------------------------------------
    /projects/libPBInvoke_vc9/ReadMe.txt:
    --------------------------------------------------------------------------------
     1 | ========================================================================
     2 |        DYNAMIC LINK LIBRARY : libPBInvoke
     3 | ========================================================================
     4 | 
     5 | 
     6 | AppWizard has created this libPBInvoke DLL for you.  
     7 | 
     8 | This file contains a summary of what you will find in each of the files that
     9 | make up your libPBInvoke application.
    10 | 
    11 | libPBInvoke.dsp
    12 |     This file (the project file) contains information at the project level and
    13 |     is used to build a single project or subproject. Other users can share the
    14 |     project (.dsp) file, but they should export the makefiles locally.
    15 | 
    16 | libPBInvoke.cpp
    17 |     This is the main DLL source file.
    18 | 
    19 | 	When created, this DLL does not export any symbols. As a result, it 
    20 | 	will not produce a .lib file when it is built. If you wish this project
    21 | 	to be a project dependency of some other project, you will either need to 
    22 | 	add code to export some symbols from the DLL so that an export library 
    23 | 	will be produced, or you can check the "doesn't produce lib" checkbox in 
    24 | 	the Linker settings page for this project. 
    25 | 
    26 | /////////////////////////////////////////////////////////////////////////////
    27 | Other standard files:
    28 | 
    29 | StdAfx.h, StdAfx.cpp
    30 |     These files are used to build a precompiled header (PCH) file
    31 |     named libPBInvoke.pch and a precompiled types file named StdAfx.obj.
    32 | 
    33 | 
    34 | /////////////////////////////////////////////////////////////////////////////
    35 | Other notes:
    36 | 
    37 | AppWizard uses "TODO:" to indicate parts of the source code you
    38 | should add to or customize.
    39 | 
    40 | 
    41 | /////////////////////////////////////////////////////////////////////////////
    42 | 
    
    
    --------------------------------------------------------------------------------
    /projects/libPBInvoke_vc9/libPBInvoke.sln:
    --------------------------------------------------------------------------------
     1 | 
     2 | Microsoft Visual Studio Solution File, Format Version 10.00
     3 | # Visual Studio 2008
     4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libPBInvoke", "libPBInvoke.vcproj", "{9585C981-9C24-4AAC-A7CA-43D2844F02B3}"
     5 | EndProject
     6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tester1", "..\tester1\tester1.vcproj", "{7E21D89F-5276-45A4-91E4-61D5C170FF0E}"
     7 | EndProject
     8 | Global
     9 | 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
    10 | 		Debug|Win32 = Debug|Win32
    11 | 		Release|Win32 = Release|Win32
    12 | 		ReleaseDemo|Win32 = ReleaseDemo|Win32
    13 | 	EndGlobalSection
    14 | 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
    15 | 		{9585C981-9C24-4AAC-A7CA-43D2844F02B3}.Debug|Win32.ActiveCfg = Debug|Win32
    16 | 		{9585C981-9C24-4AAC-A7CA-43D2844F02B3}.Debug|Win32.Build.0 = Debug|Win32
    17 | 		{9585C981-9C24-4AAC-A7CA-43D2844F02B3}.Release|Win32.ActiveCfg = Release|Win32
    18 | 		{9585C981-9C24-4AAC-A7CA-43D2844F02B3}.Release|Win32.Build.0 = Release|Win32
    19 | 		{9585C981-9C24-4AAC-A7CA-43D2844F02B3}.ReleaseDemo|Win32.ActiveCfg = ReleaseDemo|Win32
    20 | 		{9585C981-9C24-4AAC-A7CA-43D2844F02B3}.ReleaseDemo|Win32.Build.0 = ReleaseDemo|Win32
    21 | 		{7E21D89F-5276-45A4-91E4-61D5C170FF0E}.Debug|Win32.ActiveCfg = Debug|Win32
    22 | 		{7E21D89F-5276-45A4-91E4-61D5C170FF0E}.Debug|Win32.Build.0 = Debug|Win32
    23 | 		{7E21D89F-5276-45A4-91E4-61D5C170FF0E}.Release|Win32.ActiveCfg = Release|Win32
    24 | 		{7E21D89F-5276-45A4-91E4-61D5C170FF0E}.Release|Win32.Build.0 = Release|Win32
    25 | 		{7E21D89F-5276-45A4-91E4-61D5C170FF0E}.ReleaseDemo|Win32.ActiveCfg = ReleaseDemo|Win32
    26 | 		{7E21D89F-5276-45A4-91E4-61D5C170FF0E}.ReleaseDemo|Win32.Build.0 = ReleaseDemo|Win32
    27 | 	EndGlobalSection
    28 | 	GlobalSection(SolutionProperties) = preSolution
    29 | 		HideSolutionNode = FALSE
    30 | 	EndGlobalSection
    31 | EndGlobal
    32 | 
    
    
    --------------------------------------------------------------------------------
    /doc/genhelp/unsupported.html:
    --------------------------------------------------------------------------------
     1 | 
     2 | 
     3 | 	Unsupported and unimplemented PBInvoke features
     4 |    
     5 | 
     6 | 
     7 | 
    8 | 11 |

    Unsupported and unimplemented PBInvoke features

    12 | 13 | 14 |

    Unsupported usage of PBInvoke

    15 | The following modes may (or may not) work but are not supported officially. 16 |
  • Using PBInvoke with PowerBuilder 5 (PBInvoke supports only PB 6 and above) 17 |
  • Machine code targets (DLL builds) 18 |
  • Web and .Net targets (WinForm, WebForm, JSP, Web services ...) 19 | 20 |

    Only P-code (PBD) builds are supported. 21 | 22 |

    Unimplemented features

    23 | 24 | The following features will be implemented in one of the future versions of PBInvoke. 25 | 26 |
  • .Net interop (calls to external .Net classes, not under .Net targets) 27 |
  • Java interop (calls to external Java classes) 28 |
  • Calls via function pointers (now only named DLL functions and PB callbacks can be called) 29 |
  • Double, float as a return type for callbacks. However pointers to such types are supported as a return type. 30 |
  • Any struct of size of more than 4 bytes as a return type for any function. 31 | However pointers to such structures are supported as a return type. 32 |
  • C++ classes, structures inherited from other structures. 33 | 34 |

    See also

    35 |
  • Supported data types 36 |
  • WinAPI constants and types 37 | 38 |
  • 39 | 42 |
    43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /doc/genhelp/winapi.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | WinAPI constants and types 4 | 5 | 6 | 7 |
    8 | 11 |

    WinAPI constants and types

    12 | 13 |

    WinAPI is most widely used as external functions in PowerBuilder. 14 | 15 |

    WinAPI constants

    16 |

    PBInvoke provides an object with many WinAPI constants, n_pi_winapi. 17 | The constants can be used without instantiation of the object via syntax: 18 |

    n_pi_winapi.CONSTANT_NAME
    19 | 
    20 | 21 |

    Example: 22 |

    lnv_SendMessage.of_invoke(Handle(w_win), n_pi_winapi.WM_KEYDOWN, 9 /*Tab*/, 0)
    23 | 
    24 | 25 | 26 |

    WinAPI types

    27 | 28 | PBInvoke has built-in support for the following WinAPI types: 29 |
    30 | TCHAR, TSTR, LPTSTR, LPCTSTR, WCHAR, WSTR, LPWSTR, LPCWSTR, CHAR, STR, LPSTR, LPCSTR, BYTE,BOOL, HWND, HINSTANCE, 31 | LPBOOL, INT, UINT, UINT_PTR, DWORD, LPDWORD, HANDLE, LRESULT, LONG, ULONG, WPARAM, LPARAM, HMODULE, HHOOK, 32 | WORD, LPWORD, SHORT, USHORT, VOID, PVOID, LPVOID, LPCVOID, FLOAT, LPSECURITY_ATTRIBUTES 33 |
    34 | 35 |

    See also

    36 |
  • Calling DLL functions using PBInvoke 37 |
  • Handling TCHAR and TSTR. Unicode/ANSI function name suffixes 38 |
  • Supported data types 39 |
  • Working with callbacks 40 | 41 | 42 | 43 | 44 |
  • 45 | 48 |
    49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/libPBInvoke.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "stdafx.h" 3 | #include "types/DataTypes.h" 4 | #include "Compiler.h" 5 | #include "Runtime.h" 6 | #include "types/TypeFactory.h" 7 | #include "Core.h" 8 | //#include 9 | //#pragma comment(lib, "Psapi.lib") 10 | //#include 11 | 12 | #define IMP __declspec(dllimport) 13 | #define A __declspec(align(4)) 14 | 15 | //typedef int iii; 16 | //struct S {char a;}; 17 | 18 | //int unsigned a; 19 | //int IMP A unsigned aa; 20 | //int unsigned IMP aaa; 21 | //IMP unsigned b; 22 | //unsigned IMP int bb; 23 | //iii IMP c; 24 | //IMP iii cc; 25 | //S IMP d; 26 | //IMP S A dd; 27 | //IMP struct {int b;} e; 28 | // struct {int b;} IMP ee; 29 | //unsigned __int8 f; 30 | //const int al = __alignof(dd); 31 | //signed unsigned g; 32 | 33 | int ff[][2][2][2]; 34 | 35 | TCHAR * CUtil::logFile = TEXT("libPbInvoke.log"); 36 | 37 | 38 | BOOL APIENTRY DllMain( HANDLE hModule, 39 | DWORD ul_reason_for_call, 40 | LPVOID lpReserved 41 | ) 42 | { 43 | switch (ul_reason_for_call) 44 | { 45 | case DLL_PROCESS_ATTACH: 46 | truncatelog(); 47 | dprintf("DllMain\n"); 48 | #ifdef _DEBUG 49 | dprintf(" DEBUG DLL\n"); 50 | #else 51 | dprintf(" RELEASE DLL\n"); 52 | #endif 53 | Core::resetState(); 54 | break; 55 | case DLL_THREAD_ATTACH: 56 | case DLL_THREAD_DETACH: 57 | case DLL_PROCESS_DETACH: 58 | break; 59 | } 60 | return TRUE; 61 | } 62 | 63 | 64 | 65 | /// debug 66 | 67 | BOOL PBCALL core_setAppHandle(DWORD handle); 68 | 69 | void debug() { 70 | //FN fn; 71 | //fn(); 72 | //void a(void i); 73 | //aaa a; 74 | //string exe = "pb600.012420654296875"; 75 | //printf("md5=%s\n", CRC::md5(exe.c_str(), exe.size()).c_str()); 76 | //return; 77 | try { 78 | CoreInstance.setUnicode(false); 79 | core_setAppHandle(1); 80 | Compiler cc; 81 | string name = cc.compileAsC("int fn(int a[]); struct S{ char a; int b[]; }"); 82 | dprintf("last name='%s'\n", name.c_str()); 83 | } 84 | catch(RuntimeException &e) { 85 | printf("'%s'\n", e.getMessage().c_str()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/types/MethodType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RawType.h" 4 | #include 5 | using namespace stdext; 6 | 7 | 8 | class IndexedMethodType: public RawType { 9 | public: 10 | IndexedMethodType(Type returnType, vector ¶mTypes, bool isStdCall = true, DWORD methodAddr = 0); 11 | virtual ~IndexedMethodType(); 12 | virtual int getPBTypeClass() { return TC_METHOD_TYPE; } 13 | inline vector &getParamTypes() { return m_paramTypes; } 14 | inline Type &getReturnType() { return m_returnType; } 15 | inline bool isStdCall() { return m_isStdCall; } 16 | inline void setStdCall(bool isStdCall) { m_isStdCall = isStdCall; } 17 | virtual string getTypeSignature(const string& pointerSig = ""); 18 | virtual bool hasTChar(); 19 | private: 20 | vector m_paramTypes; 21 | Type m_returnType; 22 | bool m_isStdCall; 23 | Library * m_library; 24 | string m_methodName; 25 | DWORD m_methodAddr; 26 | static string buildTypeSignature(const string &pointerName, const string &methodName, Type returnType, vector ¶mTypes, bool isStdCall = true); 27 | 28 | }; 29 | 30 | 31 | class MethodType: public RawType { 32 | public: 33 | MethodType(Type returnType, vector ¶ms, bool isStdCall = true); 34 | virtual int getPBTypeClass() { return TC_METHOD_TYPE; } 35 | inline vector &getParams() { return m_params; } 36 | inline Type &getReturnType() { return m_indexedMethodType->getReturnType(); } 37 | inline bool isStdCall() { return m_indexedMethodType->isStdCall(); } 38 | inline void setStdCall(bool isStdCall) {m_indexedMethodType->setStdCall(isStdCall); } 39 | virtual string getTypeSignature(const string& pointerSig = ""); 40 | virtual bool isCompatible(BaseType* type); 41 | virtual int getItemIndex(const string& itemName); 42 | virtual bool hasTChar() { return m_indexedMethodType->hasTChar(); } 43 | private: 44 | IndexedMethodType *m_indexedMethodType; 45 | vector m_params; 46 | string buildTypeSignature(const string &pointerName); 47 | hash_map m_paramNameMap; 48 | void init(); 49 | }; 50 | 51 | -------------------------------------------------------------------------------- /doc/genhelp/handling-tchar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Handling TCHAR and TSTR. Unicode/ANSI function name suffixes 4 | 5 | 6 | 7 |
    8 | 11 |

    Handling TCHAR and TSTR. Unicode/ANSI function name suffixes

    12 |

    When at least one of parameter types or return type of a declared DLL function is based on TCHAR type, 13 | then PBInvoke automatically appends a suffix "A" or "W" to the function's name and treats TCHAR as char or wchar_t 14 | depending on PowerBuilder version. 15 |

    In Unicode versions (PB10 and above), the "W" suffix is appended and TCHAR=wchar_t, 16 |

    In ANSI version (PB9 and below) , the "A" suffix is appended and TCHAR=char. 17 | 18 |

    If the function with the suffix does not exist in the DLL, then PBInvoke tries to find the function without the prefix. 19 | 20 |

    Example: 21 |

    lnv_CreateDirectory = lnv_kernel32.of_declare_method(&
    22 |    "BOOL CreateDirectory(LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);")
    23 | // The exact meaning of the declaration above depends on PB version:
    24 | // in PB9:  BOOL CreateDirectoryA(const char *lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
    25 | // in PB10: BOOL CreateDirectoryW(const wchar_t *lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
    26 | 
    27 | 28 |

    See also

    29 |
  • Handling strings (char*, wchar_t*) 30 |
  • WinAPI constants and types 31 |
  • Working with callbacks 32 |
  • 33 | 36 |
    37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/DynCallback.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #define DYNCALLBACKVERSION "1.4.0" 9 | /* 10 | history 11 | 12 | 1.4.0 13 | - added method for calling __int64 functions 14 | 15 | 1.3.0 16 | - added method for calling float functions 17 | 18 | 1.2.0 19 | - added methods for calling functions dynamically 20 | 21 | 1.1.0 22 | - added calling convention arg (stdCall=true) to ctor 23 | 24 | 1.0.1 25 | - disabled optimization 26 | - added dumpThunk debug method 27 | 28 | 1.0.0 29 | - initial version 30 | */ 31 | 32 | 33 | class InvalidCallbackTemplateException { 34 | public: 35 | std::string msg; 36 | InvalidCallbackTemplateException(const std::string &msg) { 37 | this->msg = msg; 38 | } 39 | 40 | }; 41 | 42 | struct Callback { 43 | virtual int CALLBACK callback() = 0; 44 | virtual ~Callback() {} 45 | }; 46 | 47 | class CallbackData : public Callback 48 | { 49 | private: 50 | enum { 51 | THIS_MARKER = 0x45454545, 52 | CALLBACK_MARKER = 0x23232323, 53 | }; 54 | std::vector m_thunk; 55 | static int CALLBACK thunk_templ(int dummy); 56 | void dump(); 57 | void adjustConstant(DWORD marker, DWORD newValue); 58 | static int CALLBACK staticCallback(CallbackData * thisPtr, DWORD *argsPtr); 59 | protected: 60 | int m_argc; 61 | DWORD *m_argsPtr; 62 | public: 63 | virtual ~CallbackData(); 64 | CallbackData(int argc, bool stdCall = true); 65 | DWORD getCallbackAddr(); 66 | 67 | int runCallback(); 68 | int runCallback(int arg1); 69 | int runCallback(int arg1, int arg2); 70 | 71 | std::string dumpThunk(); 72 | 73 | // interface Callback 74 | virtual int CALLBACK callback(); 75 | }; 76 | 77 | 78 | DWORD runDynamicMethod(DWORD addr, DWORD *argv, int argc, bool isStdCall = true); 79 | 80 | double runDynamicDoubleMethod(DWORD addr, DWORD *argv, int argc, bool isStdCall = true); 81 | float runDynamicFloatMethod(DWORD addr, DWORD *argv, int argc, bool isStdCall = true); 82 | __int64 runDynamicInt64Method(DWORD addr, DWORD *argv, int argc, bool isStdCall = true); 83 | -------------------------------------------------------------------------------- /src/types/RawType.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | 3 | #include "RawType.h" 4 | #include "../DynCallback.h" 5 | #include "../Runtime.h" 6 | #include "../PBException.h" 7 | 8 | 9 | RawType::RawType(const string &typeSignature, size_t sizeOf) 10 | : m_typeSignature(typeSignature) 11 | , m_sizeOf(sizeOf) 12 | { 13 | } 14 | 15 | 16 | //void RawType::setData(ExecutionContext *context, BYTE * cBuf, BYTE * pbBuf) 17 | //{ 18 | // dprintf("+RawType::setData cBuf=%p, pbBuf=%p\n", cBuf, pbBuf); 19 | // memcpy(cBuf, pbBuf, m_sizeOf); 20 | // dprintf("-RawType::setData\n"); 21 | //} 22 | // 23 | // 24 | //void RawType::getData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf) 25 | //{ 26 | // memcpy(pbBuf, cBuf, m_sizeOf); 27 | //} 28 | 29 | void RawType::executeMethod(ExecutionContext *context, DWORD methodAddr, BYTE * retBuf, BYTE *paramBuf, int paramBufSize, bool isStdCall) 30 | { 31 | dprintf("+RawType::executeMethod paramBuf=%p, paramBufSize=%i\n", paramBuf, paramBufSize); 32 | dprintf("+RawType::executeMethod paramBuf data=%p %p\n", ((DWORD *)paramBuf)[0], ((DWORD *)paramBuf)[1]); 33 | DWORD *argv = (DWORD *)paramBuf; 34 | int argc = paramBufSize / sizeof(DWORD); 35 | *(DWORD*)retBuf = runDynamicMethod(methodAddr, argv, argc, isStdCall); 36 | dprintf("-RawType::executeMethod"); 37 | } 38 | 39 | void RawType::getArrayData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int &arrayLen, DataCharset charset) 40 | { 41 | //throw RuntimeException(context, "getStringData() is not implemented for this type"); 42 | memcpy(pbBuf, cBuf, getSizeOf() * arrayLen); 43 | 44 | } 45 | 46 | void RawType::setArrayData(ExecutionContext *context, BYTE * &cBuf, BYTE *pbBuf, int arrayLen, DataCharset charset) 47 | { 48 | if (cBuf == NULL) { 49 | allocateBuffer(context, /*out*/ cBuf, arrayLen); 50 | } 51 | memcpy(cBuf, pbBuf, getSizeOf() * arrayLen); 52 | } 53 | 54 | void RawType::allocateBuffer(ExecutionContext *context, BYTE * &buf, int itemCount) 55 | { 56 | int byteSize = getSizeOf() * itemCount; 57 | buf = context->allocateBuffer(byteSize, getAlign()); 58 | if (buf != NULL) 59 | memset(buf, 0, byteSize); 60 | } 61 | 62 | void RawType::setZeroData(ExecutionContext *context, BYTE * buf) 63 | { 64 | if (buf != NULL) 65 | memset(buf, 0, m_sizeOf); 66 | } 67 | 68 | 69 | string RawType::getTypeSignature(const string& pointerSig) 70 | { 71 | if (pointerSig != "") 72 | return m_typeSignature + pointerSig; 73 | else 74 | return m_typeSignature; 75 | } 76 | -------------------------------------------------------------------------------- /src/StdAfx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma warning(disable: 4786) 3 | #pragma warning(disable: 4800) 4 | #pragma warning(disable: 4996) 5 | 6 | //#define _DEBUG_MSG 7 | 8 | #define NOMINMAX 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | 18 | #define DLLEXPORT __declspec(dllexport) 19 | #define PBCALL __stdcall 20 | 21 | 22 | #ifdef _DEBUG_MSG 23 | #define dprintf CUtil::putMsg 24 | #define dwprintf CUtil::wputMsg 25 | #define truncatelog CUtil::deleteLog 26 | #else 27 | #define dprintf if (0) CUtil::nullMsg 28 | #define dwprintf if (0) CUtil::wnullMsg 29 | #define truncatelog if (0) CUtil::deleteLog 30 | #endif 31 | 32 | #define IsUnicode(marker) (marker[1] == 0) 33 | 34 | class CUtil 35 | { 36 | public: 37 | static TCHAR * logFile; 38 | static TCHAR * clone(TCHAR * src); 39 | CUtil(); 40 | virtual ~CUtil(); 41 | 42 | static void deleteLog() { 43 | _tunlink(logFile); 44 | } 45 | static void putMsg(TCHAR * fmt, ...) { 46 | FILE *f = openLog(); 47 | va_list marker; 48 | va_start( marker, fmt ); 49 | _vftprintf(f, fmt, marker); 50 | _vtprintf(fmt, marker); 51 | if (fmt[0]==TEXT('-') ) { 52 | _tprintf("\n\n"); 53 | _ftprintf(f, "\n\n"); 54 | } 55 | va_end( marker ); 56 | closeLog(f); 57 | } 58 | static void wputMsg(wchar_t * fmt, ...) { 59 | FILE *f = openLog(); 60 | va_list marker; 61 | va_start( marker, fmt ); 62 | vfwprintf(f, fmt, marker); 63 | va_end( marker ); 64 | closeLog(f); 65 | } 66 | static inline void nullMsg(TCHAR * fmt, ...) { 67 | } 68 | static inline void wnullMsg(wchar_t * fmt, ...) { 69 | } 70 | static inline char * toString(int v) { 71 | static char buf[20]; 72 | sprintf(buf, "%i", v); 73 | return buf; 74 | } 75 | static wstring toLower(const wstring &s) { 76 | wstring res = s; 77 | _wcslwr((wchar_t*)res.c_str()); 78 | return res; 79 | } 80 | static string toLower(const string &s) { 81 | string res = s; 82 | strlwr((char*)res.c_str()); 83 | return res; 84 | } 85 | private: 86 | static FILE * openLog() { 87 | FILE *f = _tfopen(logFile, TEXT("at+")); 88 | #ifdef _UNICODE 89 | //_ftprintf(f, TEXT("W>")); 90 | #else 91 | //_ftprintf(f, TEXT("A>")); 92 | #endif 93 | return f; 94 | } 95 | static void closeLog(FILE*f) { 96 | if (f) 97 | fclose(f); 98 | } 99 | 100 | 101 | 102 | }; 103 | 104 | -------------------------------------------------------------------------------- /doc/handling-strings.html: -------------------------------------------------------------------------------- 1 |

    Handling strings (char*, wchar_t*)

    2 | 3 |

    Charset conversion

    4 | When a function parameter is declared as char* or wchar_t*, 5 | PBInvoke automatically converts the charset of the string if PowerBuilder 6 | native strings have different charset. 7 | 8 | 9 | lnv_fn1 = lnv_somelib.of_declare_method("int strlen(char*s)") 10 | lnv_fn2 = lnv_somelib.of_declare_method("int wcslen(wchar_t*s)") 11 | 12 | // in PB9 13 | ll_len = lnv_fn1.of_invoke("test") // no conversion, both caller and callee are ANSI 14 | ll_len = lnv_fn2.of_invoke("test") // implicitly converts the string from ANSI to Unicode 15 | 16 | // in PB10+ 17 | ll_len = lnv_fn1.of_invoke("test") // implicitly converts the string from Unicode to ANSI 18 | ll_len = lnv_fn2.of_invoke("test") // no conversion, both caller and callee are Unicode 19 | 20 | 21 | Combinations of char and wchar_t in one function are supported as well. 22 | 23 | lnv_fn = lnv_somelib.of_declare_method("void some_fn(char*s1, wchar_t*s2)") 24 | // in PB9 25 | lb_res = lnv_fn.of_invoke("test1", "test2") // "test1" - no conversion 26 | // "test2" - ANSI -> Unicode 27 | // in PB10 - vice versa 28 | 29 | 30 |

    31 | Special handling is performed for TCHAR based parameters. 32 | See Handling TCHAR and TSTR. Unicode/ANSI function name suffixes. 33 | 34 |

    Passing numeric address of string instead of string

    35 | 36 | If you got an address of some string as a numeric value, for example as a result of calling another function, 37 | you can pass this number instead of a PB string value. Passing 0 or null value gives NULL string pointers. 38 |

    If a numeric address is passed instead of a string then no charset conversion is done. 39 | 40 | 41 | lnv_fn = lnv_somelib.of_declare_method("void some_fn(char*s)") 42 | 43 | lnv_s = lnv_core.of_create_value_of(LPSTR) // LPSTR is char* in WinAPI 44 | lnv_fn.of_invoke(lnv_s.of_get_ptr()) // of_get_ptr() gets the numeric value of the pointer 45 | 46 | // incorrect use: 47 | lnv_s = lnv_core.of_create_value_of(LPWSTR) // LPWSTR is wchar_t* in WinAPI 48 | lnv_fn.of_invoke(lnv_s.of_get_ptr()) // WRONG! because no conversion is done, 49 | // and the function expects char* and not wchar_t* 50 | // passing NULL 51 | lnv_fn.of_invoke(0) 52 | SetNull(ls_null) 53 | lnv_fn.of_invoke(ls_null) 54 | 55 | 56 | 57 |

    See also

    58 |
  • Handling TCHAR and TSTR. Unicode/ANSI function name suffixes 59 | 60 | -------------------------------------------------------------------------------- /doc/supported-data-types.html: -------------------------------------------------------------------------------- 1 |

    Supported data types

    2 | 3 |

    Simple types

    4 | 5 | The folowing C/C++ types are supported 6 |
      7 |
    • short, int, long, longlong and their signed/unsigned versions 8 |
    • char, wchar_t - character types 9 |
    • double, float 10 |
    • void - return type for procedures 11 |
    12 | 13 |

    Structure types

    14 | 15 |
      16 |
    • struct - a record of fields of any type 17 |
    • union - a struct whose fields share the same memory. 18 |
    19 | For structs/unions the packing attribute can be specified. See the reference. 20 | 21 |

    Pointer types

    22 |
      23 |
    • pointer to type (*) 24 |
    • reference to type (&) 25 |
    26 | 27 | 28 |

    Function prototypes

    29 |
      30 |
    • external function prototype 31 |
    • pointer to function (callback). 32 |
    33 | For functions and function pointers a few attributes are supported. See the reference. 34 | 35 | 36 |

    User-defined types

    37 | A developer can declare any custom C type using one or more C typedef operators separated by ";" and 38 | passed as a string to n_pi_core.of_declare(), as follows: 39 | 40 | n_pi_core lnv_core 41 | lnv_core.of_declare(" & 42 | typedef void *LPCITEMIDLIST, *LPITEMIDLIST; & 43 | typedef int (CALLBACK* BFFCALLBACK)(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData); & 44 | ") 45 | 46 | 47 | 48 |

    WinAPI types

    49 |

    The most widely used WinAPI types are predeclared in PBInvoke. 50 |

    These are: 51 | TCHAR, TSTR, LPTSTR, LPCTSTR, WCHAR, WSTR, LPWSTR, LPCWSTR, CHAR, STR, LPSTR, LPCSTR, BYTE,BOOL, HWND, HINSTANCE, 52 | LPBOOL, INT, UINT, UINT_PTR, DWORD, LPDWORD, HANDLE, LRESULT, LONG, ULONG, WPARAM, LPARAM, HMODULE, HHOOK, 53 | WORD, LPWORD, SHORT, USHORT, VOID, PVOID, LPVOID, LPCVOID, FLOAT, LPSECURITY_ATTRIBUTES 54 | 55 | 56 |

    Not supported

    57 |
  • Double, float as a return type for callbacks. However pointers to such types are supported as a return type. 58 |
  • Any struct of size of more than 4 bytes as a return type for any function. 59 | However pointers to such structures are supported as a return type. 60 |
  • Classes. 61 |
  • Structures inherited from other structures. 62 | 63 |

    See also

    64 |
  • Handling strings (char*, wchar_t*) 65 |
  • Handling TCHAR and TSTR. Unicode/ANSI function name suffixes 66 |
  • WinAPI constants and types 67 |
  • Working with C/C++ structures/unions 68 |
  • Working with callbacks 69 |
  • Unsupported and unimplemented PBInvoke features 70 | 71 | -------------------------------------------------------------------------------- /src/types/TypeFactory.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | 3 | #include "TypeFactory.h" 4 | #include "../Runtime.h" 5 | #include "../Core.h" 6 | #include "DataTypes.h" 7 | #include "../PBException.h" 8 | #include "../Compiler.h" 9 | 10 | 11 | 12 | TypeFactory * TypeFactory::m_instance = NULL; 13 | 14 | 15 | Type TypeFactory::createType(const string &typeName) 16 | { 17 | return CoreInstance.findType("", typeName); 18 | } 19 | 20 | 21 | 22 | 23 | TypeFactory& TypeFactory::getInstance() 24 | { 25 | if (m_instance == NULL) 26 | m_instance = new TypeFactory(); 27 | return *m_instance; 28 | } 29 | 30 | BaseType* PBCALL bt_create(char *typeName, DataCharset charset) 31 | { 32 | PBExceptionStorageInstance.clearLastExceptionMessage(); 33 | ParamStorage ps; 34 | if (charset == DC_UNICODE) 35 | typeName = ps.convertWtoA((wchar_t*)typeName); 36 | try { 37 | Type typeRef = CoreInstance.findType("", typeName); 38 | return typeRef.get(); 39 | } 40 | catch (...) { 41 | return NULL; 42 | } 43 | } 44 | 45 | 46 | Type TypeFactory::createMethodType(const char* methodDecl) 47 | { 48 | // try 1st if method ptr name was passed 49 | string methodPtrName = methodDecl; 50 | Type methodPtrType = CoreInstance.findType("", methodPtrName, false); 51 | if (methodPtrType.get() == NULL) { 52 | // no method with methodDecl name 53 | // compile declaration 54 | Compiler compiler(""); 55 | methodPtrName = compiler.compileAsCTypedef(methodDecl); 56 | if (methodPtrName == "") 57 | throw RuntimeException("Declaration does not contain function declarations: '" + string(methodDecl) + "'"); 58 | methodPtrType = CoreInstance.findType("", methodPtrName); 59 | } 60 | dprintf("TypeFactory::createMethodType: class=%i, decl='%s', sig='%s'\n", methodPtrType->getPBTypeClass(), methodPtrName.c_str(), methodPtrType->getTypeSignature().c_str()); 61 | if (methodPtrType->getPBTypeClass() == TC_METHOD_TYPE) { 62 | return methodPtrType; 63 | } 64 | else if (methodPtrType->isPointerToMethod()) { 65 | return ((PointerType*)methodPtrType.get())->getDataType(); 66 | } 67 | else { 68 | throw RuntimeException("Name '" + methodPtrName + "' is not a 'function' declaration"); 69 | } 70 | 71 | } 72 | 73 | MethodType* PBCALL tf_createMethodType(const char *methodDecl, DataCharset charset) 74 | { 75 | dprintf("tf_createMethodType charset=%i\n", charset); 76 | PBExceptionStorageInstance.clearLastExceptionMessage(); 77 | try { 78 | ParamStorage ps; 79 | if (charset == DC_UNICODE) { 80 | methodDecl = ps.convertWtoA((wchar_t*)methodDecl); 81 | } 82 | return (MethodType*)TypeFactory::getInstance().createMethodType(methodDecl).get(); 83 | } 84 | catch(...) { 85 | return NULL; 86 | } 87 | } 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /src/Core.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma warning(disable: 4786) 4 | 5 | #include "Runtime.h" 6 | #include "WinHooks.h" 7 | 8 | #include 9 | 10 | // breaks VC6 compatibility 11 | #include 12 | using namespace stdext; 13 | 14 | 15 | #define PBM_CUSTOM01 (WM_USER + 0) 16 | 17 | 18 | class Core : public ExecutionContext 19 | { 20 | public: 21 | Type& registerType(Type &typeRef); 22 | static Core& getInstance(); 23 | /** Gets current packing for structures */ 24 | int getPack(); 25 | void setPack(int pack); 26 | void pushPack(int pack); 27 | void popPack(); 28 | void setCallbackMessageHandler(HWND callbackMessageHandler); 29 | void setCallbackMessageId(UINT callbackMessageId); 30 | inline HWND getCallbackMessageHandler() { return m_callbackMessageHandler; } 31 | inline UINT getCallbackMessageId() { return m_callbackMessageId; } 32 | Type& findType(const string &nameSpace, const string& typeName, bool throwNotFound = true); 33 | Type& defineType(const string &nameSpace, const string& typeName, Type &typeRef); 34 | Type& findName(const string &nameSpace, const string& name, bool throwNotFound = true); 35 | Type& defineName(const string &nameSpace, const string& name, Type &typeRef); 36 | void compile(const string &nameSpace, const string& source); 37 | static void resetState(); 38 | void initTChar(); 39 | inline bool isUnicode() { return m_isUnicode; } 40 | inline void setUnicode(bool isUnicode) { m_isUnicode = isUnicode; } 41 | inline vector& getWinHookHelpers() { return m_winHookHelpers;} 42 | inline bool getDefCallingConvention() { return m_defCallingConvention;} 43 | inline void setDefCallingConvention(bool isStdCall) { m_defCallingConvention = isStdCall;} 44 | private: 45 | static Core * m_instance; 46 | Core(); 47 | virtual ~Core(); 48 | Core(Core&) {} 49 | Core& operator=(Core&) {} 50 | 51 | /** All types seen by PBInvoke */ 52 | vector m_types; 53 | /** Map typesig -> type index in m_types */ 54 | hash_map m_typeMap; 55 | /** Map typename -> type index in m_types */ 56 | hash_map m_typeDefs; 57 | /** Map var or fn name -> type index in m_types */ 58 | hash_map m_names; 59 | 60 | vector m_winHookHelpers; 61 | int m_pack; 62 | 63 | stack m_packStack; 64 | HWND m_callbackMessageHandler; 65 | UINT m_callbackMessageId; 66 | int m_maxInternalTypeIndex; 67 | void initInternalTypes(void); 68 | void initInternalNames(void); 69 | inline void registerType(Type &typeRef, int &typeIndex); 70 | bool m_isTCharInitialized; 71 | bool m_isUnicode; 72 | bool m_defCallingConvention; 73 | 74 | void initWinAPI(); 75 | void initWinHookHelpers(); 76 | 77 | }; 78 | 79 | #define CoreInstance Core::getInstance() 80 | 81 | 82 | -------------------------------------------------------------------------------- /doc/quick-start-guide.html: -------------------------------------------------------------------------------- 1 |

    PBInvoke quick start guide

    2 | 3 |

    Add PBInvoke library to your project

    4 |
      5 |
    • Unpack PbInvoke.PBL and libPbInvoke.DLL for your PowerBuilder version (or closest older version) to your project folder. 6 |
    • Add PbInvoke.PBL to application's library list. 7 |
    • Make a migration. 8 |
    • Make a full build. 9 |
    10 | 11 |

    Initialize PBInvoke

    12 | If libPbInvoke.DLL is not in the PATH nor in the current directory then you'll need to specify the path to it 13 | in application's open event before any other call to the library: 14 | 15 | n_pi_loader lnv_loader // autoinstantiated 16 | lnv_loader.of_preload_dll("modules\libPBInvoke.dll") 17 | 18 | Note, you can change the path only, and not the DLL name because it is hard-coded in the external function declarations. 19 | 20 | 21 |

    Declare DLL function

    22 | 23 | This code can be placed in any convenient script. Usually it's executed once per application session 24 | and its results are cached somewhere (e.g. in instance/shared variables). 25 | 26 | n_pi_core lnv_core 27 | n_pi_library lnv_user32 28 | n_pi_method lnv_SendMessage 29 | 30 | lnv_user32 = lnv_core.of_declare_library("user32.dll") 31 | 32 | lnv_SendMessage = lnv_user32.of_declare_method(& 33 | "LRESULT WINAPI SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) ") 34 | 35 | 36 | Note, that the declaration is a C function prototype which can be directly copied from C header files 37 | or from documentation such as MSDN. 38 |

    39 | HWND, UINT etc. are Windows types. Many such types are predefined in PBInvoke. 40 | But if you get "Type 'XXXX' not found" error message, then you'll need to define the type yourself 41 | before using it in declarations. 42 | 43 | n_pi_core lnv_core 44 | lnv_core.of_declare("typedef int NEWTYPE"); // this is just an example; for real typedef you'll need to 45 | // see the documentation or header files for DLL you call. 46 | 47 | ...of_declare_method(...) 48 | 49 | 50 | 51 |

    Call DLL function

    52 | 53 | 54 | long ll_result 55 | ll_result = lnv_SendMessage.of_invoke(Handle(w_somewin), n_pi_winapi.WM_KEYDOWN, 9 /*Tab*/, 0) 56 | 57 | n_pi_winapi provides some WinAPI constants. 58 | 59 |

    More samples

    60 | See the Samples folder in the archive for more complex examples with structures, callbacks etc. 61 | 62 |

    See also

    63 |
  • Calling DLL functions using PBInvoke 64 |
  • Handling strings (char*, wchar_t*) 65 |
  • WinAPI constants and types 66 |
  • Working with C/C++ structures/unions 67 |
  • Working with callbacks 68 | -------------------------------------------------------------------------------- /src/Compiler.cpp: -------------------------------------------------------------------------------- 1 | // this must be included before stdafx.h 2 | #include "parser/CParser.tab.h" 3 | 4 | #include "stdafx.h" 5 | #include "Compiler.h" 6 | #include 7 | #include "parser/CLexer.h" 8 | #include "Runtime.h" 9 | #include "PBException.h" 10 | 11 | //typedef int *FN1(), FN2(); 12 | //int *fn(); 13 | //FN1 v1; 14 | //FN2 v2; 15 | 16 | Compiler::Compiler(const string &nameSpace, bool enableTCharSuffix) 17 | : m_nameSpace(nameSpace) 18 | , m_enableTCharSuffix(m_enableTCharSuffix) 19 | { 20 | //v1(); 21 | } 22 | 23 | Compiler::~Compiler() 24 | { 25 | 26 | } 27 | 28 | 29 | string Compiler::compileAsC(const char* source) 30 | { 31 | dprintf("compileAsC\n%s\n", source); 32 | yy::CParser parser(*this); 33 | istrstream is(source); 34 | CLexer lexer(&is); 35 | int result = parser.parse(); 36 | if (result != 0) 37 | throw RuntimeException(/*"Syntax error: " + */ m_errorMessage); 38 | if (m_names.size() == 0) 39 | return ""; 40 | else 41 | return m_names[m_names.size() - 1]; 42 | } 43 | string Compiler::compileAsCTypedef(const string &source) 44 | { 45 | string typedefSource = "typedef " + source; 46 | dprintf("compileAsCTypedef: %s\n", typedefSource.c_str()); 47 | yy::CParser parser(*this); 48 | istrstream is(typedefSource.c_str()); 49 | CLexer lexer(&is); 50 | int result = parser.parse(); 51 | if (result != 0) 52 | throw RuntimeException(/*"Syntax error: " + */ m_errorMessage); 53 | if (m_typeDefs.size() == 0) 54 | return ""; 55 | else 56 | return m_typeDefs[m_typeDefs.size() - 1]; 57 | } 58 | Type Compiler::findType(const string& typeName, bool throwNotFound) 59 | { 60 | Type type = m_tags[typeName]; 61 | if (type.get() == NULL) 62 | type = CoreInstance.findType(m_nameSpace, typeName, throwNotFound); 63 | return type; 64 | } 65 | 66 | Type Compiler::defineType(const string& typeName, Type &typeRef) 67 | { 68 | if (typeName != "") { 69 | Type type = CoreInstance.defineType(m_nameSpace, typeName, typeRef); 70 | m_typeDefs.push_back(typeName); 71 | return type; 72 | } 73 | else { 74 | return typeRef; 75 | } 76 | } 77 | Type Compiler::defineTag(const string& typeName, Type &typeRef) 78 | { 79 | if (typeName != "") { 80 | m_tags[typeName] = typeRef; 81 | } 82 | return typeRef; 83 | } 84 | 85 | Type Compiler::defineName(string name, Type &typeRef) 86 | { 87 | if (typeRef->isVoid()) 88 | throw RuntimeException("Illegal use of 'void' type for declaring '" + name + "'"); 89 | if (m_enableTCharSuffix && typeRef->hasTChar()) { 90 | if (CoreInstance.isUnicode()) { 91 | name += "W"; 92 | } 93 | else { 94 | name += "A"; 95 | } 96 | } 97 | Type type = CoreInstance.defineName(m_nameSpace, name, typeRef); 98 | m_names.push_back(name); 99 | return type; 100 | } 101 | -------------------------------------------------------------------------------- /src/parser/stack.hh: -------------------------------------------------------------------------------- 1 | /* A Bison parser, made by GNU Bison 2.1. */ 2 | 3 | /* stack handling for Bison C++ parsers, 4 | Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2, or (at your option) 9 | any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | Boston, MA 02110-1301, USA. */ 20 | 21 | #ifndef BISON_STACK_HH 22 | # define BISON_STACK_HH 23 | 24 | #include 25 | 26 | namespace yy 27 | { 28 | template > 29 | class stack 30 | { 31 | public: 32 | 33 | // Hide our reversed order. 34 | typedef typename S::reverse_iterator iterator; 35 | typedef typename S::const_reverse_iterator const_iterator; 36 | 37 | stack () : seq_ () 38 | { 39 | } 40 | 41 | stack (unsigned int n) : seq_ (n) 42 | { 43 | } 44 | 45 | inline 46 | T& 47 | operator [] (unsigned int i) 48 | { 49 | return seq_[i]; 50 | } 51 | 52 | inline 53 | const T& 54 | operator [] (unsigned int i) const 55 | { 56 | return seq_[i]; 57 | } 58 | 59 | inline 60 | void 61 | push (const T& t) 62 | { 63 | seq_.push_front (t); 64 | } 65 | 66 | inline 67 | void 68 | pop (unsigned int n = 1) 69 | { 70 | for (; n; --n) 71 | seq_.pop_front (); 72 | } 73 | 74 | inline 75 | unsigned int 76 | height () const 77 | { 78 | return seq_.size (); 79 | } 80 | 81 | inline const_iterator begin () const { return seq_.rbegin (); } 82 | inline const_iterator end () const { return seq_.rend (); } 83 | 84 | private: 85 | 86 | S seq_; 87 | }; 88 | 89 | /// Present a slice of the top of a stack. 90 | template > 91 | class slice 92 | { 93 | public: 94 | 95 | slice (const S& stack, 96 | unsigned int range) : stack_ (stack), 97 | range_ (range) 98 | { 99 | } 100 | 101 | inline 102 | const T& 103 | operator [] (unsigned int i) const 104 | { 105 | return stack_[range_ - i]; 106 | } 107 | 108 | private: 109 | 110 | const S& stack_; 111 | unsigned int range_; 112 | }; 113 | } 114 | 115 | #endif // not BISON_STACK_HH 116 | -------------------------------------------------------------------------------- /doc/help.hhc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
      11 |
    • 12 | 13 | 14 | 15 |
        16 |
      • 17 | 18 | 19 | 20 | 21 |
      • 22 | 23 | 24 | 25 | 26 |
      27 |
    • 28 | 29 | 30 |
        31 |
      • 32 | 33 | 34 | 35 | 36 |
      • 37 | 38 | 39 | 40 | 41 |
      • 42 | 43 | 44 | 45 | 46 |
      • 47 | 48 | 49 | 50 | 51 |
      • 52 | 53 | 54 | 55 | 56 |
      57 |
    • 58 | 59 | 60 |
        61 |
      • 62 | 63 | 64 | 65 | 66 |
      • 67 | 68 | 69 | 70 | 71 |
      72 |
    • 73 | 74 | 75 | 76 | 77 |
    • 78 | 79 | 80 | 81 | 82 |
    83 | 84 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 |

    PBInvoke library

    2 | 3 |

    Summary

    4 | PBInvoke is a PowerBuilder library for calling external DLL functions with arbitrary 5 | parameter and return types - structures, unions, pointers, etc. including 6 | function pointers to PowerBuilder methods callable from DLL code as callbacks. 7 | 8 | 9 |

    PBInvoke goals

    10 |
      11 | 12 |
    • Allow PowerBuilder developers to work in PowerScript with complex data structures without 13 | writing wrapper DLLs in other languages such as C/C++. 14 | 15 |
    • Make declarations of external functions ANSI/Unicode-independent which avoids migration issues 16 | when using the same code across ANSI and Unicode versions of PowerBuilder. 17 | 18 |
    • Support any C/C++ data type (except classes). This includes complex nested data types involving 19 | structs, unions, pointers, simple types and their combinations. 20 | 21 |
    • Support not only STDCALL calling convention, but also CDECL which is default in C/C++ programs. 22 | 23 |
    • Allow PB code to be called from external functions as callbacks with full access to passed parameters. 24 | 25 |
    • Support wide range of PowerBuilder versions from PB 6 to PB 11.5 and any future version. 26 | 27 |
    28 | 29 | 30 |

    Why not use native PowerBuilder external functions?

    31 | 32 | PowerBuilder support of external functions has the following restrictions 33 | which make developers write wrapper code in C/C++ and compile it with third party compilers. 34 |
      35 |
    • No support for PowerBuilder callbacks. 36 |
    • No support for unions and pointers to complex data types in structures. 37 |
    • External function declarations depend on string encoding expected by functions. 38 | Often a charset conversion is required between ANSI PB and Unicode DLL and vice versa. 39 | PowerScript attrubute ';ansi' is available only in PB10+ and makes the source code incompatible with older PB versions. 40 | PBInvoke automatically handles the encoding stuff (including function name suffixes such as A/W in WinAPI). 41 | 42 |
    43 | 44 |

    Why not use PowerBuilder extensions (PBNI)?

    45 | 46 |
      47 |
    • PBNI is available only as of PB9. 48 |
    • PBNI requires knowledge of C++. 49 |
    • PBNI extensions are quite hard to write and debug. 50 |
    • PBNI requires separate DLLs for ANSI and Unicode versions. 51 |
    52 | 53 | 54 | 55 |

    See also

    56 |
  • Quick Start Guide 57 |
  • Calling DLL functions using PBInvoke 58 |
  • Handling strings (char*, wchar_t*) 59 |
  • Handling TCHAR and TSTR. Unicode/ANSI function name suffixes 60 |
  • Supported data types 61 |
  • WinAPI constants and types 62 |
  • Working with C/C++ structures/unions 63 |
  • Working with callbacks 64 |
  • Unsupported and unimplemented PBInvoke features 65 |
  • PBInvoke library license agreement 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /doc/genhelp/help.hhc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
      11 |
    • 12 | 13 | 14 | 15 |
        16 |
      • 17 | 18 | 19 | 20 | 21 |
      • 22 | 23 | 24 | 25 | 26 |
      27 |
    • 28 | 29 | 30 |
        31 |
      • 32 | 33 | 34 | 35 | 36 |
      • 37 | 38 | 39 | 40 | 41 |
      • 42 | 43 | 44 | 45 | 46 |
      • 47 | 48 | 49 | 50 | 51 |
      • 52 | 53 | 54 | 55 | 56 |
      57 |
    • 58 | 59 | 60 |
        61 |
      • 62 | 63 | 64 | 65 | 66 |
      • 67 | 68 | 69 | 70 | 71 |
      72 |
    • 73 | 74 | 75 | 76 | 77 |
    • 78 | 79 | 80 | 81 | 82 |
    83 | 84 | -------------------------------------------------------------------------------- /doc/genhelp/supported-data-types.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Supported data types 4 | 5 | 6 | 7 |
    8 | 11 |

    Supported data types

    12 | 13 |

    Simple types

    14 | 15 | The folowing C/C++ types are supported 16 |
      17 |
    • short, int, long, longlong and their signed/unsigned versions 18 |
    • char, wchar_t - character types 19 |
    • double, float 20 |
    • void - return type for procedures 21 |
    22 | 23 |

    Structure types

    24 | 25 |
      26 |
    • struct - a record of fields of any type 27 |
    • union - a struct whose fields share the same memory. 28 |
    29 | For structs/unions the packing attribute can be specified. See the reference. 30 | 31 |

    Pointer types

    32 |
      33 |
    • pointer to type (*) 34 |
    • reference to type (&) 35 |
    36 | 37 | 38 |

    Function prototypes

    39 |
      40 |
    • external function prototype 41 |
    • pointer to function (callback). 42 |
    43 | For functions and function pointers a few attributes are supported. See the reference. 44 | 45 | 46 |

    User-defined types

    47 | A developer can declare any custom C type using one or more C typedef operators separated by ";" and 48 | passed as a string to n_pi_core.of_declare(), as follows: 49 |
    n_pi_core lnv_core
    50 | lnv_core.of_declare(" &
    51 | 	typedef void *LPCITEMIDLIST, *LPITEMIDLIST; &
    52 | 	typedef int (CALLBACK* BFFCALLBACK)(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData); &
    53 | 	")
    54 | 
    55 | 
    56 | 57 |

    WinAPI types

    58 |

    The most widely used WinAPI types are predeclared in PBInvoke. 59 |

    These are: 60 | TCHAR, TSTR, LPTSTR, LPCTSTR, WCHAR, WSTR, LPWSTR, LPCWSTR, CHAR, STR, LPSTR, LPCSTR, BYTE,BOOL, HWND, HINSTANCE, 61 | LPBOOL, INT, UINT, UINT_PTR, DWORD, LPDWORD, HANDLE, LRESULT, LONG, ULONG, WPARAM, LPARAM, HMODULE, HHOOK, 62 | WORD, LPWORD, SHORT, USHORT, VOID, PVOID, LPVOID, LPCVOID, FLOAT, LPSECURITY_ATTRIBUTES 63 | 64 | 65 |

    Not supported

    66 |
  • Double, float as a return type for callbacks. However pointers to such types are supported as a return type. 67 |
  • Any struct of size of more than 4 bytes as a return type for any function. 68 | However pointers to such structures are supported as a return type. 69 |
  • Classes. 70 |
  • Structures inherited from other structures. 71 | 72 |

    See also

    73 |
  • Handling strings (char*, wchar_t*) 74 |
  • Handling TCHAR and TSTR. Unicode/ANSI function name suffixes 75 |
  • WinAPI constants and types 76 |
  • Working with C/C++ structures/unions 77 |
  • Working with callbacks 78 |
  • Unsupported and unimplemented PBInvoke features 79 | 80 | 81 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /src/parser/clexer.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "CLexer.h" 3 | #include 4 | 5 | //#define YY_DECL int CLexer::yylex(YYSTYPE* yylval) 6 | //#define YY_DECL int yyFlexLexer::yylex(YYSTYPE* yylval) 7 | 8 | #define YY_DECL int yylex(YYSTYPE* yylval) 9 | #define YY_INPUT(buf,result,max_size) \ 10 | { \ 11 | CLexer::in()->read(buf, max_size);\ 12 | result = CLexer::in()->bad() ? YY_NULL : CLexer::in()->gcount();\ 13 | } 14 | 15 | 16 | stack m_buffers; 17 | 18 | 19 | %} 20 | 21 | %option 8bit 22 | 23 | /*%option c++ */ 24 | /*%option yyclass="CLexer"*/ 25 | %option outfile="CLexer.cpp" 26 | %option nounistd 27 | /*%option prefix="CLexer" */ 28 | 29 | id0 [a-zA-Z_] 30 | id {id0}({id0}|[0-9@])* 31 | int [0-9]+ 32 | num1 {int}("."{int})?([eE][+-]?{int})? 33 | num2 "."{int}([eE][+-]?{int})? 34 | num {num1}|{num2} 35 | sp [ \t]* 36 | sp1 [ \t]+ 37 | 38 | 39 | %x COMM 40 | 41 | %% 42 | 43 | [ \t\r\n]+ /*skip spaces*/ 44 | "//"[^\n]* /*// comments*/ 45 | "/*" { BEGIN(COMM); } /* / * * / comments*/ 46 | [^\*]+ { } 47 | "*"+ { } 48 | "*"+"/" { BEGIN(INITIAL); } 49 | NEAR|FAR|near|far {} 50 | typedef { return T_TYPEDEF; } 51 | __cdecl|CDECL { return ATTR_CDECL; } 52 | __stdcall|CALLBACK|WINAPI|STDCALL|PASCAL|pascal { return ATTR_STDCALL; } 53 | struct { return T_STRUCT; } 54 | union { return T_UNION; } 55 | enum { return T_ENUM; } 56 | const /* ignore */ 57 | unsigned { return T_UNSIGNED; } 58 | signed { return T_SIGNED; } 59 | char { return T_CHAR;} 60 | wchar_t { return T_WCHAR_T;} 61 | int { return T_INT;} 62 | __int8 { return T_INT8;} 63 | __int16 { return T_INT16;} 64 | __int32 { return T_INT32;} 65 | __int64 { return T_INT64;} 66 | short { return T_SHORT;} 67 | long { return T_LONG;} 68 | longlong { return T_LONGLONG;} 69 | double { return T_DOUBLE;} 70 | float { return T_FLOAT;} 71 | void { return T_VOID;} 72 | __declspec { return ATTR_DECLSPEC; } 73 | ";" { return SEMICOLON; } 74 | "::" { return DBLCOLON; } 75 | "=" { return ASSIGN; } 76 | "," { return COMMA; } 77 | "(" { return LPAREN; } 78 | ")" { return RPAREN; } 79 | "{" { return LCURL; } 80 | "}" { return RCURL; } 81 | "[" { return LBRACKET; } 82 | "]" { return RBRACKET; } 83 | "*" { return STAR; } 84 | "&" { return ADDR; } 85 | {id} { yylval->text = yytext; return ID; } 86 | {num} { yylval->text = yytext; return NUM; } 87 | "#"{sp}pragma{sp1}pack { return T_PRAGMA_PACK; } 88 | "#"{sp}pragma[^\n]* /* ignore unknown pragmas */ 89 | . /* ignore */ 90 | %% 91 | 92 | 93 | int yywrap() 94 | { 95 | return 1; // terminate on eof 96 | } 97 | 98 | istream * CLexer::m_inputStream; 99 | 100 | void CLexer::pushInput() 101 | { 102 | m_prevInputStream = m_inputStream; 103 | m_buffers.push(YY_CURRENT_BUFFER); 104 | yy_switch_to_buffer(yy_create_buffer(NULL, YY_BUF_SIZE)); 105 | } 106 | void CLexer::popInput() 107 | { 108 | yy_delete_buffer(YY_CURRENT_BUFFER); 109 | m_inputStream = m_prevInputStream; 110 | yy_switch_to_buffer(m_buffers.top()); 111 | m_buffers.pop(); 112 | } 113 | 114 | -------------------------------------------------------------------------------- /doc/genhelp/quick-start-guide.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | PBInvoke quick start guide 4 | 5 | 6 | 7 |
    8 | 11 |

    PBInvoke quick start guide

    12 | 13 |

    Add PBInvoke library to your project

    14 |
      15 |
    • Unpack PbInvoke.PBL and libPbInvoke.DLL for your PowerBuilder version (or closest older version) to your project folder. 16 |
    • Add PbInvoke.PBL to application's library list. 17 |
    • Make a migration. 18 |
    • Make a full build. 19 |
    20 | 21 |

    Initialize PBInvoke

    22 | If libPbInvoke.DLL is not in the PATH nor in the current directory then you'll need to specify the path to it 23 | in application's open event before any other call to the library: 24 |
    n_pi_loader lnv_loader  // autoinstantiated
    25 | lnv_loader.of_preload_dll("modules\libPBInvoke.dll")
    26 | 
    27 | Note, you can change the path only, and not the DLL name because it is hard-coded in the external function declarations. 28 | 29 | 30 |

    Declare DLL function

    31 | 32 | This code can be placed in any convenient script. Usually it's executed once per application session 33 | and its results are cached somewhere (e.g. in instance/shared variables). 34 |
    n_pi_core lnv_core
    35 | n_pi_library lnv_user32 
    36 | n_pi_method lnv_SendMessage 
    37 | 
    38 | lnv_user32 = lnv_core.of_declare_library("user32.dll")
    39 | 
    40 | lnv_SendMessage = lnv_user32.of_declare_method(&
    41 | 	"LRESULT WINAPI SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) ")
    42 | 
    43 | 44 | Note, that the declaration is a C function prototype which can be directly copied from C header files 45 | or from documentation such as MSDN. 46 |

    47 | HWND, UINT etc. are Windows types. Many such types are predefined in PBInvoke. 48 | But if you get "Type 'XXXX' not found" error message, then you'll need to define the type yourself 49 | before using it in declarations. 50 |

    n_pi_core lnv_core
    51 | lnv_core.of_declare("typedef int NEWTYPE"); // this is just an example; for real typedef you'll need to 
    52 |                                             // see the documentation or header files for DLL you call.
    53 | 
    54 | ...of_declare_method(...)
    55 | 
    56 | 57 | 58 |

    Call DLL function

    59 | 60 |
    long ll_result
    61 | ll_result = lnv_SendMessage.of_invoke(Handle(w_somewin), n_pi_winapi.WM_KEYDOWN, 9 /*Tab*/, 0) 
    62 | 
    63 | n_pi_winapi provides some WinAPI constants. 64 | 65 |

    More samples

    66 | See the Samples folder in the archive for more complex examples with structures, callbacks etc. 67 | 68 |

    See also

    69 |
  • Calling DLL functions using PBInvoke 70 |
  • Handling strings (char*, wchar_t*) 71 |
  • WinAPI constants and types 72 |
  • Working with C/C++ structures/unions 73 |
  • Working with callbacks 74 | 75 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /src/types/StructType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RawType.h" 4 | #include 5 | using namespace stdext; 6 | 7 | class IndexedStructType: public RawType { 8 | public: 9 | IndexedStructType(vector &itemTypes, int pack = 8, int explicitAlign = 0, bool isUnion = false, bool isArgStack = false); 10 | IndexedStructType(const string& body, int pack = 8, int explicitAlign = 0, bool isUnion = false, bool isArgStack = false); 11 | 12 | virtual int getPBTypeClass() {return TC_STRUCT_TYPE; } 13 | virtual int getSizeOf() {return m_sizeOf; } 14 | 15 | virtual int getItemOffset(int itemIndex) {return m_itemOffsets[itemIndex]; } 16 | inline vector& getItemTypes() { return m_itemTypes; } 17 | inline vector& getItemOffsets() { return m_itemOffsets; } 18 | inline int getPack() { return m_pack; } 19 | virtual string getTypeSignature(const string& pointerSig = ""); 20 | virtual int getExplicitAlign() { return m_explicitAlign; } 21 | virtual int getAlign() { return m_align; } 22 | inline bool isArgStack() { return m_isArgStack; } 23 | inline bool isUnion() { return m_isUnion; } 24 | virtual bool hasTChar(); 25 | 26 | private: 27 | 28 | /** Item types */ 29 | vector m_itemTypes; 30 | 31 | /** Item offsets in the structure */ 32 | vector m_itemOffsets; 33 | 34 | /** Is the structure a union (all offsets == 0)? */ 35 | bool m_isUnion; 36 | 37 | /** Packing of items, the value of #pragma pack(n) */ 38 | int m_pack; 39 | 40 | /** Explicitly given alignment of the structure in memory, the value of __declspec(align(n)) for struct */ 41 | int m_explicitAlign; 42 | 43 | /** Is the structure for arg stack storage. */ 44 | bool m_isArgStack; 45 | 46 | /** Effective alignment of the structure in memory */ 47 | int m_align; 48 | 49 | 50 | string buildTypeSignature(const string &pointerSig); 51 | void parseBody(const string &body); 52 | protected: 53 | void init(); 54 | }; 55 | 56 | 57 | class StructType: public RawType { 58 | public: 59 | StructType(vector &items, int pack = 8, int explicitAlign = 0, bool isUnion = false, bool isArgStack = false); 60 | //incomplete struct def 61 | StructType(const string &tagName); 62 | void complete(vector &items, int pack = 8, int explicitAlign = 0, bool isUnion = false, bool isArgStack = false); 63 | 64 | virtual int getPBTypeClass() {return TC_STRUCT_TYPE; } 65 | virtual int getSizeOf() {return m_indexedStructType->getSizeOf(); } 66 | 67 | virtual int getItemOffset(int itemIndex) {return m_indexedStructType->getItemOffset(itemIndex); } 68 | inline vector& getItems() { return m_items; } 69 | inline vector& getItemOffsets() { return m_indexedStructType->getItemOffsets(); } 70 | inline int getPack() { return m_indexedStructType->getPack(); } 71 | virtual string getTypeSignature(const string& pointerSig = ""); 72 | virtual int getExplicitAlign() { return m_indexedStructType->getExplicitAlign(); } 73 | virtual int getAlign() { return m_indexedStructType->getAlign(); } 74 | virtual bool isComplete() { return m_indexedStructType != NULL; } 75 | virtual string getTagName() { return m_tagName; } 76 | virtual bool isCompatible(BaseType* type); 77 | virtual int getItemIndex(const string& itemName) ; 78 | virtual bool hasTChar() { return m_indexedStructType->hasTChar(); } 79 | 80 | private: 81 | 82 | IndexedStructType *m_indexedStructType; 83 | 84 | /** Item names and types*/ 85 | vector m_items; 86 | 87 | hash_map m_itemNameMap; 88 | string m_tagName; 89 | 90 | string buildTypeSignature(const string &pointerSig); 91 | void init(); 92 | }; 93 | -------------------------------------------------------------------------------- /doc/genhelp/handling-strings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Handling strings (char*, wchar_t*) 4 | 5 | 6 | 7 |
    8 | 11 |

    Handling strings (char*, wchar_t*)

    12 | 13 |

    Charset conversion

    14 | When a function parameter is declared as char* or wchar_t*, 15 | PBInvoke automatically converts the charset of the string if PowerBuilder 16 | native strings have different charset. 17 | 18 |
    lnv_fn1 = lnv_somelib.of_declare_method("int strlen(char*s)")
    19 | lnv_fn2 = lnv_somelib.of_declare_method("int wcslen(wchar_t*s)")
    20 | 
    21 | // in PB9
    22 | ll_len = lnv_fn1.of_invoke("test") // no conversion, both caller and callee are ANSI
    23 | ll_len = lnv_fn2.of_invoke("test") // implicitly converts the string from ANSI to Unicode
    24 | 
    25 | // in PB10+ 
    26 | ll_len = lnv_fn1.of_invoke("test") // implicitly converts the string from Unicode to ANSI
    27 | ll_len = lnv_fn2.of_invoke("test") // no conversion, both caller and callee are Unicode
    28 | 
    29 | 30 | Combinations of char and wchar_t in one function are supported as well. 31 |
    lnv_fn = lnv_somelib.of_declare_method("void some_fn(char*s1, wchar_t*s2)")
    32 | // in PB9
    33 | lb_res = lnv_fn.of_invoke("test1", "test2") // "test1" - no conversion
    34 |                                             // "test2" - ANSI -> Unicode
    35 | // in PB10 - vice versa
    36 | 
    37 | 38 |

    39 | Special handling is performed for TCHAR based parameters. 40 | See Handling TCHAR and TSTR. Unicode/ANSI function name suffixes. 41 | 42 |

    Passing numeric address of string instead of string

    43 | 44 | If you got an address of some string as a numeric value, for example as a result of calling another function, 45 | you can pass this number instead of a PB string value. Passing 0 or null value gives NULL string pointers. 46 |

    If a numeric address is passed instead of a string then no charset conversion is done. 47 | 48 |

    lnv_fn = lnv_somelib.of_declare_method("void some_fn(char*s)")
    49 | 
    50 | lnv_s = lnv_core.of_create_value_of(LPSTR) //  LPSTR is char* in WinAPI
    51 | lnv_fn.of_invoke(lnv_s.of_get_ptr())       //  of_get_ptr() gets the numeric value of the pointer
    52 | 
    53 | // incorrect use:
    54 | lnv_s = lnv_core.of_create_value_of(LPWSTR) // LPWSTR is wchar_t* in WinAPI
    55 | lnv_fn.of_invoke(lnv_s.of_get_ptr())       // WRONG! because no conversion is done, 
    56 |                                             // and the function expects char* and not wchar_t*
    57 | // passing NULL
    58 | lnv_fn.of_invoke(0) 
    59 | SetNull(ls_null)
    60 | lnv_fn.of_invoke(ls_null) 
    61 | 
    62 | 
    63 | 64 |

    See also

    65 |
  • Handling TCHAR and TSTR. Unicode/ANSI function name suffixes 66 | 67 | 68 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /doc/genhelp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | PBInvoke library 4 | 5 | 6 | 7 |
    8 | 11 |

    PBInvoke library

    12 | 13 |

    Summary

    14 | PBInvoke is a PowerBuilder library for calling external DLL functions with arbitrary 15 | parameter and return types - structures, unions, pointers, etc. including 16 | function pointers to PowerBuilder methods callable from DLL code as callbacks. 17 | 18 | 19 |

    PBInvoke goals

    20 |
      21 | 22 |
    • Allow PowerBuilder developers to work in PowerScript with complex data structures without 23 | writing wrapper DLLs in other languages such as C/C++. 24 | 25 |
    • Make declarations of external functions ANSI/Unicode-independent which avoids migration issues 26 | when using the same code across ANSI and Unicode versions of PowerBuilder. 27 | 28 |
    • Support any C/C++ data type (except classes). This includes complex nested data types involving 29 | structs, unions, pointers, simple types and their combinations. 30 | 31 |
    • Support not only STDCALL calling convention, but also CDECL which is default in C/C++ programs. 32 | 33 |
    • Allow PB code to be called from external functions as callbacks with full access to passed parameters. 34 | 35 |
    • Support wide range of PowerBuilder versions from PB 6 to PB 11.5 and any future version. 36 | 37 |
    38 | 39 | 40 |

    Why not use native PowerBuilder external functions?

    41 | 42 | PowerBuilder support of external functions has the following restrictions 43 | which make developers write wrapper code in C/C++ and compile it with third party compilers. 44 |
      45 |
    • No support for PowerBuilder callbacks. 46 |
    • No support for unions and pointers to complex data types in structures. 47 |
    • External function declarations depend on string encoding expected by functions. 48 | Often a charset conversion is required between ANSI PB and Unicode DLL and vice versa. 49 | PowerScript attrubute ';ansi' is available only in PB10+ and makes the source code incompatible with older PB versions. 50 | PBInvoke automatically handles the encoding stuff (including function name suffixes such as A/W in WinAPI). 51 | 52 |
    53 | 54 |

    Why not use PowerBuilder extensions (PBNI)?

    55 | 56 |
      57 |
    • PBNI is available only as of PB9. 58 |
    • PBNI requires knowledge of C++. 59 |
    • PBNI extensions are quite hard to write and debug. 60 |
    • PBNI requires separate DLLs for ANSI and Unicode versions. 61 |
    62 | 63 | 64 | 65 |

    See also

    66 |
  • Quick Start Guide 67 |
  • Calling DLL functions using PBInvoke 68 |
  • Handling strings (char*, wchar_t*) 69 |
  • Handling TCHAR and TSTR. Unicode/ANSI function name suffixes 70 |
  • Supported data types 71 |
  • WinAPI constants and types 72 |
  • Working with C/C++ structures/unions 73 |
  • Working with callbacks 74 |
  • Unsupported and unimplemented PBInvoke features 75 |
  • PBInvoke library license agreement 76 | 77 | 78 | 79 | 80 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/types/CharType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PointerType.h" 4 | #include "../Runtime.h" 5 | 6 | class CharType: public RawType { 7 | protected: 8 | CharType(const string &typeSignature, size_t sizeOf); 9 | public: 10 | virtual int getPBTypeClass() { return TC_CHAR_TYPE; }; 11 | //inline void setPBUnicode(bool isPBUnicode) { m_isPBUnicode = isPBUnicode;} 12 | protected: 13 | //bool m_isPBUnicode; 14 | string TypeName; 15 | string StringFormat; 16 | }; 17 | 18 | class ACharType: public CharType { 19 | protected: 20 | typedef char type_t; 21 | typedef wchar_t inv_type_t; 22 | enum {CHARSET = DC_ANSI, INV_CHARSET = DC_UNICODE }; 23 | inline size_t tstrlen(const type_t* s) { return strlen(s);} 24 | inline size_t tstrnlen(const type_t* s, size_t n) { return strnlen(s, n);} 25 | inline size_t strlenStoT(ExecutionContext* ctx, const type_t *srcString, int strLen = -1) { 26 | return ctx->strlenAtoW(srcString, strLen); 27 | } 28 | inline size_t strlenTtoS(ExecutionContext* ctx, const inv_type_t *srcString, int strLen = -1) { 29 | return ctx->strlenWtoA(srcString, strLen); 30 | } 31 | inline inv_type_t* convertStoT(ExecutionContext* ctx, const type_t *srcString, int strLen = -1, inv_type_t *buf = NULL) { 32 | return ctx->convertAtoW(srcString, strLen, buf); 33 | } 34 | inline type_t* convertTtoS(ExecutionContext* ctx, const inv_type_t *srcString, int strLen = -1, type_t *buf = NULL) { 35 | return ctx->convertWtoA(srcString, strLen, buf); 36 | } 37 | public: 38 | 39 | ACharType() : CharType("char", sizeof(char)) { TypeName = "ACharType"; StringFormat = "s"; } 40 | virtual void setArrayData(ExecutionContext *context, BYTE * &cBuf, BYTE *pbBuf, int strLen, DataCharset charset); 41 | virtual void getArrayData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int &strLen, DataCharset charset); 42 | virtual size_t strLen(ExecutionContext *context, BYTE * buf, int arrayLen, DataCharset charset); 43 | }; 44 | class WCharType: public CharType { 45 | protected: 46 | typedef wchar_t type_t; 47 | typedef char inv_type_t; 48 | enum {CHARSET = DC_UNICODE, INV_CHARSET = DC_ANSI }; 49 | inline size_t tstrlen(const type_t* s) { return wcslen(s);} 50 | inline size_t tstrnlen(const type_t* s, size_t n) { return wcsnlen(s, n);} 51 | inline size_t strlenStoT(ExecutionContext* ctx, const type_t *srcString, int strLen = -1) { 52 | return ctx->strlenWtoA(srcString, strLen); 53 | } 54 | inline size_t strlenTtoS(ExecutionContext* ctx, const inv_type_t *srcString, int strLen = -1) { 55 | return ctx->strlenAtoW(srcString, strLen); 56 | } 57 | inline inv_type_t* convertStoT(ExecutionContext* ctx, const type_t *srcString, int strLen = -1, inv_type_t *buf = NULL) { 58 | return ctx->convertWtoA(srcString, strLen, buf); 59 | } 60 | inline type_t* convertTtoS(ExecutionContext* ctx, const inv_type_t *srcString, int strLen = -1, type_t *buf = NULL) { 61 | return ctx->convertAtoW(srcString, strLen, buf); 62 | } 63 | 64 | public: 65 | WCharType() : CharType("wchar_t", sizeof(wchar_t)) { TypeName = "WCharType"; StringFormat = "S"; } 66 | virtual void setArrayData(ExecutionContext *context, BYTE * &cBuf, BYTE *pbBuf, int strLen, DataCharset charset); 67 | virtual void getArrayData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int &strLen, DataCharset charset); 68 | virtual size_t strLen(ExecutionContext *context, BYTE * buf, int arrayLen, DataCharset charset); 69 | }; 70 | 71 | 72 | class TACharType: public ACharType { 73 | public: 74 | virtual string getTypeSignature(const string& pointerSig = "") { return "tchar_t" + pointerSig;} 75 | virtual bool hasTChar() { return true; } 76 | }; 77 | 78 | class TWCharType: public WCharType { 79 | public: 80 | virtual string getTypeSignature(const string& pointerSig = "") { return "tchar_t" + pointerSig;} 81 | virtual bool hasTChar() { return true; } 82 | }; 83 | 84 | -------------------------------------------------------------------------------- /src/parser/location.hh: -------------------------------------------------------------------------------- 1 | /* A Bison parser, made by GNU Bison 2.1. */ 2 | 3 | /* Location class for Bison C++ parsers, 4 | Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2, or (at your option) 9 | any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | Boston, MA 02110-1301, USA. */ 20 | 21 | /** 22 | ** \file location.hh 23 | ** Define the location class. 24 | */ 25 | 26 | #ifndef BISON_LOCATION_HH 27 | # define BISON_LOCATION_HH 28 | 29 | # include 30 | # include 31 | # include "position.hh" 32 | 33 | namespace yy 34 | { 35 | 36 | /// Abstract a location. 37 | class location 38 | { 39 | /** \name Ctor & dtor. 40 | ** \{ */ 41 | public: 42 | /// Construct a location. 43 | location () : 44 | begin (), 45 | end () 46 | { 47 | } 48 | /** \} */ 49 | 50 | 51 | /** \name Line and Column related manipulators 52 | ** \{ */ 53 | public: 54 | /// Reset initial location to final location. 55 | inline void step () 56 | { 57 | begin = end; 58 | } 59 | 60 | /// Extend the current location to the COUNT next columns. 61 | inline void columns (unsigned int count = 1) 62 | { 63 | end += count; 64 | } 65 | 66 | /// Extend the current location to the COUNT next lines. 67 | inline void lines (unsigned int count = 1) 68 | { 69 | end.lines (count); 70 | } 71 | /** \} */ 72 | 73 | 74 | public: 75 | /// Beginning of the located region. 76 | position begin; 77 | /// End of the located region. 78 | position end; 79 | }; 80 | 81 | /// Join two location objects to create a location. 82 | inline const location operator+ (const location& begin, const location& end) 83 | { 84 | location res = begin; 85 | res.end = end.end; 86 | return res; 87 | } 88 | 89 | /// Add two location objects. 90 | inline const location operator+ (const location& begin, unsigned int width) 91 | { 92 | location res = begin; 93 | res.columns (width); 94 | return res; 95 | } 96 | 97 | /// Add and assign a location. 98 | inline location& operator+= (location& res, unsigned int width) 99 | { 100 | res.columns (width); 101 | return res; 102 | } 103 | 104 | /** \brief Intercept output stream redirection. 105 | ** \param ostr the destination output stream 106 | ** \param loc a reference to the location to redirect 107 | ** 108 | ** Avoid duplicate information. 109 | */ 110 | inline std::ostream& operator<< (std::ostream& ostr, const location& loc) 111 | { 112 | position last = loc.end - 1; 113 | ostr << loc.begin; 114 | if (last.filename 115 | && (!loc.begin.filename 116 | || *loc.begin.filename != *last.filename)) 117 | ostr << '-' << last; 118 | else if (loc.begin.line != last.line) 119 | ostr << '-' << last.line << '.' << last.column; 120 | else if (loc.begin.column != last.column) 121 | ostr << '-' << last.column; 122 | return ostr; 123 | } 124 | 125 | } 126 | 127 | #endif // not BISON_LOCATION_HH 128 | -------------------------------------------------------------------------------- /src/parser/position.hh: -------------------------------------------------------------------------------- 1 | /* A Bison parser, made by GNU Bison 2.1. */ 2 | 3 | /* Position class for Bison C++ parsers, 4 | Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2, or (at your option) 9 | any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | Boston, MA 02110-1301, USA. */ 20 | 21 | /** 22 | ** \file position.hh 23 | ** Define the position class. 24 | */ 25 | 26 | #ifndef BISON_POSITION_HH 27 | # define BISON_POSITION_HH 28 | 29 | # include 30 | # include 31 | 32 | namespace yy 33 | { 34 | /// Abstract a position. 35 | class position 36 | { 37 | public: 38 | /// Initial column number. 39 | static const unsigned int initial_column = 0; 40 | /// Initial line number. 41 | static const unsigned int initial_line = 1; 42 | 43 | /** \name Ctor & dtor. 44 | ** \{ */ 45 | public: 46 | /// Construct a position. 47 | position () : 48 | filename (0), 49 | line (initial_line), 50 | column (initial_column) 51 | { 52 | } 53 | /** \} */ 54 | 55 | 56 | /** \name Line and Column related manipulators 57 | ** \{ */ 58 | public: 59 | /// (line related) Advance to the COUNT next lines. 60 | inline void lines (int count = 1) 61 | { 62 | column = initial_column; 63 | line += count; 64 | } 65 | 66 | /// (column related) Advance to the COUNT next columns. 67 | inline void columns (int count = 1) 68 | { 69 | int leftmost = initial_column; 70 | int current = column; 71 | if (leftmost <= current + count) 72 | column += count; 73 | else 74 | column = initial_column; 75 | } 76 | /** \} */ 77 | 78 | public: 79 | /// File name to which this position refers. 80 | std::string* filename; 81 | /// Current line number. 82 | unsigned int line; 83 | /// Current column number. 84 | unsigned int column; 85 | }; 86 | 87 | /// Add and assign a position. 88 | inline const position& 89 | operator+= (position& res, const int width) 90 | { 91 | res.columns (width); 92 | return res; 93 | } 94 | 95 | /// Add two position objects. 96 | inline const position 97 | operator+ (const position& begin, const int width) 98 | { 99 | position res = begin; 100 | return res += width; 101 | } 102 | 103 | /// Add and assign a position. 104 | inline const position& 105 | operator-= (position& res, const int width) 106 | { 107 | return res += -width; 108 | } 109 | 110 | /// Add two position objects. 111 | inline const position 112 | operator- (const position& begin, const int width) 113 | { 114 | return begin + -width; 115 | } 116 | 117 | /** \brief Intercept output stream redirection. 118 | ** \param ostr the destination output stream 119 | ** \param pos a reference to the position to redirect 120 | */ 121 | inline std::ostream& 122 | operator<< (std::ostream& ostr, const position& pos) 123 | { 124 | if (pos.filename) 125 | ostr << *pos.filename << ':'; 126 | return ostr << pos.line << '.' << pos.column; 127 | } 128 | 129 | } 130 | #endif // not BISON_POSITION_HH 131 | -------------------------------------------------------------------------------- /doc/genhelp/license.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | PBInvoke library license agreement 4 | 5 | 6 | 7 |
    8 | 11 |

    PBInvoke library license agreement

    12 |
    Using the product indicates your acknowledgment that you have read this 
    13 | license and agree to its terms. 
    14 | 
    15 | By installing, copying or otherwise using the SOFTWARE, you agree to be 
    16 | bound by the terms of this LICENSE.
    17 | 
    18 | Warning: The SOFTWARE is protected by copyright laws and international 
    19 | copyright treaties, as well as other intellectual property laws and treaties. 
    20 | The SOFTWARE is licensed, not sold.
    21 | 
    22 | The copyright holder of the SOFTWARE is Anatoly Moskovsky <avm@sqlbatch.com>
    23 | 
    24 | The program is a shareware. You may evaluate it for period of 30 days. 
    25 | After this period you may not use the Software unless you pay the 
    26 | registration fee. You may share the unregistered Software with other 
    27 | people only if the Software is distributed in this original setup package. 
    28 | You may not give the registration numbers or registered versions of 
    29 | this software to other people nor use other people's registration/registered 
    30 | version.
    31 | 
    32 | GRANT OF LICENSE 
    33 | 
    34 | This LICENSE grants you the following rights:
    35 | 
    36 | a. Single Application License. You may create commercial applications based on 
    37 | PBInvoke and distribute them with your executables. No royalties required.
    38 | One license is required per application. This is enforced by binding 
    39 | PBInvoke to application's executable name. 
    40 | You may NOT create a distributable component/library that include PBInvoke. 
    41 | 
    42 | b. Multi Application License. You may create commercial applications based on 
    43 | PBInvoke and distribute them with your executables. No royalties required.
    44 | Any number of applications are allowed with one license. 
    45 | You may NOT create a distributable component/library that include PBInvoke. 
    46 | 
    47 | c. Library License. You may create unlimited number of commercial applications,
    48 | components or libraries based on PBInvoke and distribute them in any form, 
    49 | provided the original PBInvoke code is not modified. No royalties required.
    50 | 
    51 | d. You may use the product by any number of developers in your organization 
    52 | at a time. 
    53 | 
    54 | e. You may use the trial version for the limited purposes of 
    55 | demonstrations, trials and design time evaluations and running a 
    56 | product tour. You may not use the trial version to produce commercial 
    57 | works.
    58 | 
    59 | f. You may not decompile, disassemble or otherwise reverse engineer 
    60 | the SOFTWARE.
    61 | 
    62 | g. You may not rent or lease the SOFTWARE.
    63 | 
    64 | h. You may NOT transfer any of your rights under this LICENSE.
    65 | 
    66 | i. Without prejudice to any other rights, the copyright holder may terminate 
    67 | this LICENSE if you fail to comply with the terms and conditions of 
    68 | this LICENSE. In such event, you must destroy all copies of the SOFTWARE 
    69 | and provide sufficient proof thereof to the copyright holder.
    70 | 
    71 | 
    72 | NO WARRANTIES.
    73 | The copyright holder expressly disclaims any warranty for the SOFTWARE PRODUCT.
    74 | THE SOFTWARE PRODUCT AND ANY RELATED DOCUMENTATION IS PROVIDED "AS IS" 
    75 | WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, 
    76 | WITHOUT LIMITATION, THE IMPLIED WARRANTIES OR MERCHANTABILITY, FITNESS 
    77 | FOR A PARTICULAR PURPOSE, OR NONINFRINGEMENT.
    78 | THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE PRODUCT 
    79 | REMAINS WITH YOU.
    80 | NO LIABILITY FOR CONSEQUENTIAL DAMAGES. IN NO EVENT SHALL THE COPYRIGHT HOLDER 
    81 | OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR 
    82 | CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES 
    83 | FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS 
    84 | INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF 
    85 | OR INABILITY TO USE THE SOFTWARE PRODUCT
    86 | 
    87 | 
    88 |
    89 | 92 |
    93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /src/types/StringType.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | 3 | #include "StringType.h" 4 | 5 | #include "../Runtime.h" 6 | #include "../PBException.h" 7 | 8 | //StringType::StringType(const string &typeSignature) 9 | // : PointerType(typeSignature) 10 | //{ 11 | //} 12 | // 13 | // 14 | //int StringType::getPBTypeClass() 15 | //{ 16 | // return TC_STRING_TYPE; 17 | //} 18 | // 19 | // 20 | // 21 | //void AStringType::setStringData(ExecutionContext *context, BYTE * cBuf, BYTE * pbBuf, int strLen, DataCharset charset) 22 | // 23 | //{ 24 | // dprintf("\n+AStringType::setStringData str=[%s]\n", pbBuf); 25 | // 26 | // // copy string value 27 | // if (pbBuf != NULL) { 28 | // if (charset == DC_ANSI || charset == DC_BINARY) { 29 | // BYTE *strValue = context->allocateBuffer((strLen + (charset == DC_BINARY ? 0 : 1)) * sizeof(char), __alignof(char)); 30 | // memcpy(strValue, pbBuf, (strLen + (charset == DC_BINARY ? 0 : 1)) * sizeof(char)); 31 | // pbBuf = strValue; 32 | // } 33 | // else { 34 | // pbBuf = (BYTE *)context->convertWtoA((wchar_t*)pbBuf, strLen); 35 | // } 36 | // } 37 | // 38 | // // copy ptr value 39 | // setData(context, cBuf, (BYTE*)&pbBuf); 40 | // 41 | // dprintf("-AStringType::setStringData\n\n"); 42 | //} 43 | // 44 | //void AStringType::getStringData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int &strLen, DataCharset charset) 45 | //{ 46 | // dprintf("+AStringType::getStringData\n"); 47 | // 48 | // char *strValue = *(char* *)cBuf; 49 | // if (strValue == NULL) { 50 | // strLen = -1; 51 | // } 52 | // else { 53 | // dprintf("strLen=%i, strValue=%p, strValue='%s'\n", strLen, strValue, strValue); 54 | // int len; 55 | // if (charset == DC_UNICODE) { 56 | // len = context->strlenAtoW(strValue); 57 | // } 58 | // else if (charset == DC_ANSI){ 59 | // len = strlen(strValue); 60 | // } 61 | // else { // DC_BINARY 62 | // len = strLen; 63 | // } 64 | // if (strLen > 0) { 65 | // if (len > strLen) // copy max strLen chars 66 | // len = strLen; 67 | // dprintf("len=%i\n", len); 68 | // if (charset == DC_UNICODE) { 69 | // context->convertAtoW(strValue, len, /*out*/(wchar_t*)pbBuf); 70 | // } 71 | // else { 72 | // memcpy(pbBuf, strValue, len * sizeof(char)); 73 | // } 74 | // } 75 | // strLen = len; 76 | // } 77 | // dprintf("-AStringType::getStringData\n"); 78 | //} 79 | // 80 | // 81 | //void WStringType::setStringData(ExecutionContext *context, BYTE * cBuf, BYTE * pbBuf, int strLen, DataCharset charset) 82 | // 83 | //{ 84 | // dprintf("\n+WStringType::setStringData\n"); 85 | // 86 | // // copy string value 87 | // if (pbBuf != NULL) { 88 | // if (charset == DC_UNICODE || charset == DC_BINARY) { 89 | // BYTE *strValue = context->allocateBuffer((strLen + (charset == DC_BINARY ? 0 : 1)) * sizeof(wchar_t), __alignof(wchar_t)); 90 | // memcpy(strValue, pbBuf, (strLen + (charset == DC_BINARY ? 0 : 1)) * sizeof(wchar_t)); 91 | // pbBuf = strValue; 92 | // } 93 | // else { 94 | // pbBuf = (BYTE *)context->convertAtoW((char*)pbBuf, strLen); 95 | // } 96 | // } 97 | // 98 | // // copy ptr value 99 | // setData(context, cBuf, (BYTE*)&pbBuf); 100 | // 101 | // dprintf("-WStringType::setStringData\n\n"); 102 | //} 103 | // 104 | //void WStringType::getStringData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int &strLen, DataCharset charset) 105 | //{ 106 | // dprintf("+WStringType::getStringData\n"); 107 | // 108 | // wchar_t *strValue = *(wchar_t* *)cBuf; 109 | // if (strValue == NULL) { 110 | // strLen = -1; 111 | // } 112 | // else { 113 | // dprintf("strLen=%i, strValue=%p, strValue='%S'\n", strLen, strValue, strValue); 114 | // int len; 115 | // if (charset == DC_ANSI) { 116 | // len = context->strlenWtoA(strValue); 117 | // } 118 | // else if (charset == DC_UNICODE) { 119 | // len = wcslen(strValue); 120 | // } 121 | // else { // DC_BINARY 122 | // len = strLen; 123 | // } 124 | // if (strLen > 0) { 125 | // if (len > strLen) // copy max strLen chars 126 | // len = strLen; 127 | // dprintf("len=%i\n", len); 128 | // if (charset == DC_ANSI) { 129 | // context->convertWtoA(strValue, len, /*out*/(char*)pbBuf); 130 | // } 131 | // else { 132 | // memcpy(pbBuf, strValue, len * sizeof(wchar_t)); 133 | // } 134 | // } 135 | // strLen = len; 136 | // } 137 | // dprintf("-WStringType::getStringData\n"); 138 | //} 139 | // 140 | // 141 | -------------------------------------------------------------------------------- /src/types/CharType.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | 3 | #include "CharType.h" 4 | 5 | #include "../Runtime.h" 6 | #include "../PBException.h" 7 | 8 | CharType::CharType(const string &typeSignature, size_t sizeOf) 9 | : RawType(typeSignature, sizeOf) 10 | { 11 | } 12 | 13 | template 14 | class Convertor: public T { 15 | public: 16 | inline size_t strLen(ExecutionContext *context, BYTE * buf, int arrayLen, DataCharset charset); 17 | inline void setArrayData(ExecutionContext *context, BYTE * &cBuf, BYTE * pbBuf, int strLen, DataCharset charset); 18 | inline void getArrayData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int &strLen, DataCharset charset); 19 | }; 20 | 21 | template 22 | inline size_t Convertor::strLen(ExecutionContext *context, BYTE * buf, int arrayLen, DataCharset charset) 23 | { 24 | size_t strLen = 0; 25 | if (buf != NULL) { 26 | if (charset == CHARSET) { 27 | strLen = tstrnlen((type_t*) buf, arrayLen); 28 | } 29 | else { 30 | strLen = strlenTtoS(context, (inv_type_t*)buf, arrayLen); 31 | } 32 | } 33 | return strLen; 34 | } 35 | 36 | template 37 | inline void Convertor::setArrayData(ExecutionContext *context, BYTE * &cBuf, BYTE * pbBuf, int strLen, DataCharset charset) 38 | { 39 | dprintf("+%s::setArrayData cBuf=%p, strLen=%i, s='%s'\n", TypeName.c_str(), cBuf ,strLen, pbBuf); 40 | 41 | if (pbBuf == NULL) 42 | throw RuntimeException(context, TypeName+ "::setArrayData pbBuf == NULL"); 43 | 44 | 45 | if (pbBuf != NULL) { 46 | if (charset == CHARSET || charset == DC_BINARY) { 47 | if (cBuf == NULL) { 48 | strLen += 1; 49 | allocateBuffer(context, cBuf, strLen); 50 | } 51 | memcpy(cBuf, pbBuf, strLen * sizeof(type_t)); 52 | } 53 | else { 54 | cBuf = (BYTE*)convertTtoS(context, (inv_type_t*)pbBuf, strLen, (type_t*)cBuf); 55 | } 56 | } 57 | 58 | dprintf("-%s::setArrayData\n", TypeName.c_str()); 59 | } 60 | 61 | template 62 | inline void Convertor::getArrayData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int &strLen, DataCharset charset) 63 | { 64 | dprintf("+%s::getArrayData cBuf=%p, strLen=%i\n", TypeName.c_str(), cBuf ,strLen); 65 | if (cBuf == NULL) 66 | throw RuntimeException(context, TypeName + "::getArrayData cBuf == NULL"); 67 | 68 | type_t *strValue = (type_t*)cBuf; 69 | dprintf("strLen=%i, strValue=%p, strValue='%s'\n", strLen, strValue, strValue); 70 | int len; 71 | if (charset == INV_CHARSET) { 72 | len = strlenStoT(context, strValue); 73 | } 74 | else if (charset == CHARSET) { 75 | len = tstrlen(strValue); 76 | } 77 | else { // DC_BINARY 78 | len = strLen; 79 | } 80 | if (strLen > 0) { 81 | if (len > strLen) // copy max strLen chars 82 | len = strLen; 83 | dprintf("len=%i\n", len); 84 | if (charset == INV_CHARSET) { 85 | convertStoT(context, strValue, len, /*out*/(inv_type_t*)pbBuf); 86 | } 87 | else { 88 | memcpy(pbBuf, strValue, len * sizeof(type_t)); 89 | } 90 | } 91 | strLen = len; 92 | dprintf("-%s::getArrayData\n", TypeName.c_str()); 93 | 94 | } 95 | 96 | static Convertor convA; 97 | static Convertor convW; 98 | 99 | size_t ACharType::strLen(ExecutionContext *context, BYTE * buf, int arrayLen, DataCharset charset) 100 | { 101 | return convA.strLen(context, buf, arrayLen, charset); 102 | } 103 | 104 | size_t WCharType::strLen(ExecutionContext *context, BYTE * buf, int arrayLen, DataCharset charset) 105 | { 106 | return convW.strLen(context, buf, arrayLen, charset); 107 | } 108 | 109 | 110 | void ACharType::setArrayData(ExecutionContext *context, BYTE * &cBuf, BYTE * pbBuf, int strLen, DataCharset charset) 111 | { 112 | convA.setArrayData(context, cBuf, pbBuf, strLen, charset); 113 | } 114 | 115 | 116 | void WCharType::setArrayData(ExecutionContext *context, BYTE * &cBuf, BYTE * pbBuf, int strLen, DataCharset charset) 117 | { 118 | convW.setArrayData(context, cBuf, pbBuf, strLen, charset); 119 | } 120 | 121 | 122 | void ACharType::getArrayData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int &strLen, DataCharset charset) 123 | { 124 | convA.getArrayData(context, cBuf, pbBuf, strLen, charset); 125 | } 126 | 127 | 128 | 129 | void WCharType::getArrayData(ExecutionContext *context, BYTE * cBuf, BYTE *pbBuf, int &strLen, DataCharset charset) 130 | { 131 | convW.getArrayData(context, cBuf, pbBuf, strLen, charset); 132 | } 133 | 134 | 135 | -------------------------------------------------------------------------------- /doc/working-with-structures.html: -------------------------------------------------------------------------------- 1 |

    Working with C/C++ structures/unions

    2 | 3 |

    PBInvoke supports full access to C++ structs/unions from PowerBuilder. 4 | 5 |

    Because there is no equivalents for unions and field types such 6 | as pointers to structures and function pointers in PowerBuilder, 7 | PBInvoke have a special object for storing such values: n_pi_value. 8 | 9 |

    Working with nested structures and unions.

    10 |

    Suppose you have the following structure declaration: 11 | n_pi_core lnv_core 12 | lnv_core.of_declare("struct MYSTR { union { int ival; char* sval;} u; char ch;}") 13 | 14 | This is a structure MYSTR which has a field of type char, 'ch', and a field of type union 'u', 15 | which itself has two fields 'ival' and 'sval', which share the same memory. 16 | 17 |

    Some examples of working with the structure: 18 | n_pi_core lnv_core 19 | n_pi_value lnv_str 20 | 21 | // Create an instance of the structure in memory 22 | // In C++: MYSTR str; 23 | lnv_str = lnv_core.of_create_value_of("MYSTR"); 24 | 25 | // Fill the structure's memory with zero bytes. 26 | // Note, however, that of_create_value_of() does it anyway. 27 | // C++: memset(&str, sizeof(MYSTR), 0); 28 | lnv_str.of_set(0) 29 | 30 | // Assign to sval field of the union 31 | // C++: str.u.sval = "test"; 32 | lnv_str.of_item("u").of_set("sval", "test") 33 | 34 | A few words regarding what does n_pi_value.of_item do. 35 | When you call of_item("fieldname"), a n_pi_value is returned which is a reference to the field. 36 | No data is copied. When you modify this reference, the original structure is modified. 37 |

    of_item() is used most often for accessing nested structures. 38 | If you have a field of a simple type (string, numeric) you use of_get("field")/of_set("field", value) 39 | instead of of_item("field"). 40 |

    Also note, that field name in of_item(), of_get(), of_set() is case sensitive. 41 | 42 | // Read the value of ival which now holds the pointer to the string "test" because ival and sval share their memory. 43 | // C++: int i = str.u.ival; 44 | ll_i = lnv_str.of_item("u").of_get("ival") 45 | 46 | // Assign to ch field of the structure 47 | // C++: str.ch = 'A'; 48 | lnv_str.of_set("ch", "A") 49 | lnv_str.of_set(2, "A") // Fields can also be accessed by a 1-based index in order of their declarations. 50 | 51 | // Pass the structure as a parameter to a function: 52 | // C++: void fn1(MYSTR s) { } 53 | // fn1(str) 54 | n_pi_method lnv_fn1 55 | lnv_fn1 = lnv_somedll.of_declare_method("void fn1(MYSTR s)") 56 | lnv_fn1.of_invoke(lnv_str) // lnv_str's value is copied. 57 | 58 | // Pass the structure as a pointer parameter to a function: 59 | // C++: void fn2(MYSTR *s) { s->u.sval = "fn2"; }; 60 | // fn2(&str) 61 | lnv_fn2 = lnv_somedll.of_declare_method("void fn2(MYSTR *s)") 62 | lnv_fn2.of_invoke(lnv_str) // implicitly gets the address of the structure 63 | //or 64 | lnv_fn2.of_invoke(lnv_str.of_get_addr()) // which is the same, but explicit. 65 | 66 | // If the structure is modified in fn2 we'll see those changes 67 | String ls_mod 68 | ls_mod = lnv_str.of_item("u").of_get("sval") // returns "fn2" 69 | 70 | 71 | 72 |

    Working with pointers to structures as fields.

    73 | Pointers to a type require dereferencing in order to allow access to the value they point to. 74 | 75 | 76 | lnv_core.of_declare("struct N { int a;}") // declare a struct 77 | lnv_core.of_declare("struct S { N* n;}") // declare a struct with nested pointer to a struct 78 | // create an instance 79 | // C++: S str; 80 | lnv_str = lnv_core.of_create_value_of("S") 81 | 82 | // init the pointer n with the address of an instance of N 83 | // C++: s.n = new N(); 84 | lnv_str.of_set("n", lnv_core.of_create_value_of("N")) 85 | 86 | // access the nested field, a 87 | // C++: str.n->a = 123; 88 | lnv_str.of_item("n").of_deref().of_set("a", 123) 89 | 90 | // get the nested structure as separate reference 91 | // C++: N &n = *str.n; 92 | lnv_n = lnv_str.of_item("n").of_deref() // note this is just a reference, not a copy. 93 | 94 | //Now lnv_n.of_get("a") is the same as lnv_str.of_item("n").of_deref().of_get("a") 95 | 96 | 97 |

    See also

    98 |
  • Handling strings (char*, wchar_t*) 99 |
  • Handling TCHAR and TSTR. Unicode/ANSI function name suffixes 100 |
  • Working with callbacks 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /src/PBCallback.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "PBCallback.h" 3 | #include "Runtime.h" 4 | #include "Core.h" 5 | #include "PBException.h" 6 | 7 | PBCallback::PBCallback(UINT callbackId, Method *defaultMethodContext) 8 | : CallbackData(defaultMethodContext->getArgStackSize() / sizeof(DWORD), defaultMethodContext->getMethodType()->isStdCall()) 9 | , m_callbackId(callbackId) 10 | , m_methodType(defaultMethodContext->getMethodType()) 11 | , m_inCall(0) 12 | , m_currentContext(NULL) 13 | , m_hookId(-1) 14 | , m_hhk(NULL) 15 | , m_enable(true) 16 | { 17 | dprintf("PBCallback::PBCallback\n"); 18 | 19 | } 20 | 21 | PBCallback::~PBCallback() 22 | { 23 | dprintf("PBCallback::~PBCallback\n"); 24 | } 25 | 26 | void PBCallback::createCallbackContext(BYTE *argsPtr) 27 | { 28 | m_inCall ++; 29 | if (m_inCall > 1 || m_contexts.empty()) { 30 | m_contexts.push(MethodContextPtr(new Method(m_methodType, argsPtr))); 31 | } 32 | else { 33 | m_contexts.top()->setArgsPtr(argsPtr); 34 | } 35 | m_currentContext = m_contexts.top().get(); 36 | 37 | } 38 | void PBCallback::destroyCallbackContext() 39 | { 40 | if (m_inCall > 1) { 41 | m_contexts.pop(); 42 | m_currentContext = m_contexts.top().get(); 43 | } 44 | m_inCall --; 45 | } 46 | 47 | void PBCallback::setHookFilter(HHOOK hhk, int hookId, UINT messageFilter[], size_t messageFilterSize) 48 | { 49 | dprintf("PBCallback::setHookFilter\n"); 50 | vector& helpers = CoreInstance.getWinHookHelpers(); 51 | if (hookId < 0 || hookId >= (int)helpers.size() || helpers[hookId].get() == NULL) { 52 | m_enable = false; 53 | throw RuntimeException("Message filter for this type of hooks is not implemented yet"); 54 | } 55 | m_hookId = hookId; 56 | m_hhk = hhk; 57 | m_messageFilter.insert(m_messageFilter.end(), &messageFilter[0], &messageFilter[messageFilterSize]); 58 | m_enable = true; 59 | } 60 | BOOL PBCALL cb_setHookFilter(PBCallback *callback, HHOOK hhk, int hookId, UINT messageFilter[], size_t messageFilterSize) 61 | { 62 | try { 63 | callback->setHookFilter(hhk, hookId, messageFilter, messageFilterSize); 64 | return true; 65 | } 66 | catch (...) { 67 | return false; 68 | } 69 | } 70 | 71 | //this method must NOT throw any exception 72 | int CALLBACK PBCallback::callback() 73 | { 74 | LRESULT result; 75 | if (!m_enable) 76 | return 0; 77 | if (m_hookId >= 0 && m_hhk != NULL) { 78 | vector& helpers = CoreInstance.getWinHookHelpers(); 79 | if (m_hookId < (int)helpers.size() && helpers[m_hookId].get() != NULL) { 80 | if (helpers[m_hookId]->skip(m_hhk, (PHookProcArgs)m_argsPtr, m_messageFilter, result)) 81 | return result; 82 | } 83 | } 84 | 85 | dprintf("+PBCallback::callback\n"); 86 | static int counter = 0; 87 | counter ++; 88 | int callbackRetVal = 0; 89 | Method *methodContext = NULL; 90 | try { 91 | HWND messageHandler = CoreInstance.getCallbackMessageHandler(); 92 | if (messageHandler == NULL) 93 | throw RuntimeException("Callback message handler is not specified"); 94 | 95 | createCallbackContext((BYTE*)m_argsPtr); 96 | dprintf("context=%p, m_argsPtr=%p\n", m_currentContext, m_argsPtr); 97 | 98 | dprintf("SendMessage incall=%i, counter=%i, messageHandler=%i, messageId=%i, m_callbackId=%i\n", 99 | m_inCall, counter, messageHandler, CoreInstance.getCallbackMessageId(), m_callbackId); 100 | result = SendMessage(messageHandler, CoreInstance.getCallbackMessageId(), m_callbackId, (LPARAM)m_currentContext); 101 | dprintf("SendMessage result=%i\n", result); 102 | if (result == 1) { 103 | // executed OK 104 | callbackRetVal = *((int*)m_currentContext->getReturnValueAddr()); 105 | } 106 | else { 107 | // callback id or message handler was not found 108 | callbackRetVal = 0; 109 | } 110 | destroyCallbackContext(); 111 | } 112 | catch (...) { 113 | destroyCallbackContext(); 114 | dprintf("-PBCallback::callback with exception\n"); 115 | } 116 | dprintf("-PBCallback::callback\n"); 117 | return callbackRetVal; 118 | } 119 | 120 | PBCallback* PBCALL cb_create(UINT callbackId, Method* methodContext) 121 | { 122 | PBExceptionStorageInstance.clearLastExceptionMessage(); 123 | try { 124 | return new PBCallback(callbackId, methodContext); 125 | } 126 | catch (...) { 127 | return NULL; 128 | } 129 | } 130 | 131 | void PBCALL cb_destroy(PBCallback* instance) 132 | { 133 | PBExceptionStorageInstance.clearLastExceptionMessage(); 134 | if (instance != NULL) 135 | delete instance; 136 | } 137 | 138 | DWORD PBCALL cb_getAddr(PBCallback* instance) 139 | { 140 | PBExceptionStorageInstance.clearLastExceptionMessage(); 141 | return instance->getCallbackAddr(); 142 | } 143 | 144 | DWORD PBCallback::getMethodAddr() 145 | { 146 | return getCallbackAddr(); 147 | } 148 | -------------------------------------------------------------------------------- /doc/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: arial, sans-serif; 3 | } 4 | 5 | h1, h2, h3 { 6 | font-family: tahoma; 7 | } 8 | 9 | h1 { 10 | } 11 | h1, h1 a { 12 | background-color1: #9ebad2; 13 | border1: dotted 1px #6e8aa2; 14 | color: #5e7a92; 15 | } 16 | 17 | h2 { 18 | border1: 1px solid #6e8aa2; 19 | background-color1: #9ebad2; 20 | color: #3e5a72; 21 | padding-top: 4px; 22 | padding-bottom: 4px; 23 | margin-bottom: 2px; 24 | border-bottom: 2px solid ; 25 | padding-left: 0; 26 | } 27 | 28 | h3 { 29 | margin: 1em 0 3px 0; 30 | padding-left: 0; 31 | color: #3e5a72; 32 | } 33 | 34 | #container { 35 | padding: 0; 36 | margin: 1% auto 0 auto; 37 | position: relative; 38 | } 39 | #main { 40 | margin-left: 0; 41 | } 42 | 43 | #footer, #header { 44 | border-top: 2px solid #3e5a72; 45 | border-bottom: 2px solid #3e5a72; 46 | margin-top: 1%; 47 | position: relative; 48 | clear: both; 49 | font-size: 70%; 50 | } 51 | 52 | #copyright { 53 | display: inline; 54 | padding-left: 2%; 55 | padding-rgiht: 2%; 56 | } 57 | #report { 58 | display: inline; 59 | padding-left: 2%; 60 | padding-rgiht: 2%; 61 | } 62 | 63 | hr { 64 | } 65 | 66 | 67 | table { 68 | border: 1px solid #808080; 69 | border-collapse: collapse; 70 | margin: 0; 71 | } 72 | td, th { 73 | border: 1px solid #8080a0; 74 | margin: 0; 75 | padding: 2px; 76 | } 77 | th { 78 | background-color: #eeeeff; 79 | color: #3e5a72; 80 | } 81 | 82 | 83 | 84 | div.section { 85 | border: 1px dotted #EEEEEE; 86 | padding: 1em; 87 | background-color1: #fffff7; 88 | 89 | } 90 | .section p { 91 | } 92 | 93 | #main p { 94 | } 95 | 96 | td.product { 97 | text-align: left; 98 | } 99 | td.price { 100 | text-align: center; 101 | } 102 | td.order { 103 | text-align: center; 104 | } 105 | 106 | a img { 107 | border: none; 108 | } 109 | 110 | .topmenu { 111 | border: 1px dotted green; 112 | padding-left: 1%; 113 | margin-top: 1%; 114 | margin-bottom: 1%; 115 | font-size: 110%; 116 | font-weight: bold; 117 | background-color: #bedaf2; 118 | width: 98.9%; 119 | display: block; 120 | position: relative; 121 | } 122 | 123 | .topmenu ol { 124 | border1: 1px dotted blue; 125 | display: inline; 126 | padding: 0; 127 | margin: 0; 128 | float: left; 129 | } 130 | .topmenu li { 131 | display: inline; 132 | border: 1px solid #8eaac2; 133 | margin: 0; 134 | padding1: 0.3em 0.8em; 135 | padding: 0; 136 | background-color: #9ebad2; 137 | list-style: none; 138 | float: left; 139 | } 140 | .topmenu a:visited, .topmenu a:link, .topmenu a:active { 141 | color: #3e5a72; 142 | text-decoration: none; 143 | } 144 | .topmenu a:hover { 145 | color: #3e5a72; 146 | text-decoration: underline; 147 | } 148 | 149 | 150 | 151 | .floatmenu { 152 | border: 1px solid #bedaf2; 153 | font-size: 110%; 154 | font-weight: bold; 155 | background-color1: #bedaf2; 156 | background-color: white; 157 | display: block; 158 | margin: 2.5em 10px 4px 10px; 159 | padding: 4px; 160 | float: right; 161 | } 162 | 163 | .floatmenu ol { 164 | border1: 1px dotted blue; 165 | display: block; 166 | padding: 0; 167 | margin: 0; 168 | } 169 | .floatmenu li { 170 | display: block; 171 | border: 2px solid ; 172 | border-color: #bedaf2 #7e9ab2 #7e9ab2 #bedaf2; 173 | margin: 0.3em 0.4em; 174 | background-color: #9ebad2; 175 | padding: 0.2em 0.6em; 176 | list-style: none; 177 | text-align: center; 178 | } 179 | .floatmenu a:visited, .floatmenu a:link, .floatmenu a:active { 180 | color: #3e5a72; 181 | text-decoration: none; 182 | } 183 | .floatmenu a:hover { 184 | color: #3e5a72; 185 | text-decoration: underline; 186 | } 187 | 188 | .floatmenu, .topmenu { 189 | font-family: Tahoma; 190 | } 191 | 192 | 193 | div.download { 194 | margin: 0.3em; 195 | padding: 0.3em; 196 | border: solid 1px #bedaf2; 197 | width: auto; 198 | color: #3e5a72; 199 | float1: left; 200 | } 201 | 202 | table.download { 203 | border: solid 1px green; 204 | font-weight: bold; 205 | margin-left: 0.5em; 206 | background1: #CCFFCC; 207 | } 208 | 209 | .download td { 210 | border: 1px solid #00CC00; 211 | padding: 10px; 212 | vertical-align: middle; 213 | } 214 | 215 | .download td, .download a:visited, .download a:link, .download a:active { 216 | color1: #3e5a72; 217 | color: #3e725a; 218 | text-decoration: none; 219 | } 220 | .download a:hover { 221 | color1: #3e5a72; 222 | color: #3e725a; 223 | text-decoration: underline; 224 | } 225 | .download td.icon { 226 | background: url(downg.png) no-repeat right center; 227 | padding-right: 0; 228 | } 229 | .download td.icon a { 230 | padding-right: 32px; 231 | margin-right: 0; 232 | border1: 1px solid red; 233 | } 234 | 235 | pre.pb { 236 | margin-left: 0.3em; 237 | padding: 0.3em; 238 | background-color1: #ccd6e0; 239 | background-color: #ffffee; 240 | border: 1px solid #ccd6e0; 241 | } 242 | pre { 243 | margin-left: 0.3em; 244 | padding: 0.3em; 245 | } 246 | 247 | .cmt { 248 | color: #5e7a92; 249 | } 250 | 251 | -------------------------------------------------------------------------------- /doc/genhelp/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: arial, sans-serif; 3 | } 4 | 5 | h1, h2, h3 { 6 | font-family: tahoma; 7 | } 8 | 9 | h1 { 10 | } 11 | h1, h1 a { 12 | background-color1: #9ebad2; 13 | border1: dotted 1px #6e8aa2; 14 | color: #5e7a92; 15 | } 16 | 17 | h2 { 18 | border1: 1px solid #6e8aa2; 19 | background-color1: #9ebad2; 20 | color: #3e5a72; 21 | padding-top: 4px; 22 | padding-bottom: 4px; 23 | margin-bottom: 2px; 24 | border-bottom: 2px solid ; 25 | padding-left: 0; 26 | } 27 | 28 | h3 { 29 | margin: 1em 0 3px 0; 30 | padding-left: 0; 31 | color: #3e5a72; 32 | } 33 | 34 | #container { 35 | padding: 0; 36 | margin: 1% auto 0 auto; 37 | position: relative; 38 | } 39 | #main { 40 | margin-left: 0; 41 | } 42 | 43 | #footer, #header { 44 | border-top: 2px solid #3e5a72; 45 | border-bottom: 2px solid #3e5a72; 46 | margin-top: 1%; 47 | position: relative; 48 | clear: both; 49 | font-size: 70%; 50 | } 51 | 52 | #copyright { 53 | display: inline; 54 | padding-left: 2%; 55 | padding-rgiht: 2%; 56 | } 57 | #report { 58 | display: inline; 59 | padding-left: 2%; 60 | padding-rgiht: 2%; 61 | } 62 | 63 | hr { 64 | } 65 | 66 | 67 | table { 68 | border: 1px solid #808080; 69 | border-collapse: collapse; 70 | margin: 0; 71 | } 72 | td, th { 73 | border: 1px solid #8080a0; 74 | margin: 0; 75 | padding: 2px; 76 | } 77 | th { 78 | background-color: #eeeeff; 79 | color: #3e5a72; 80 | } 81 | 82 | 83 | 84 | div.section { 85 | border: 1px dotted #EEEEEE; 86 | padding: 1em; 87 | background-color1: #fffff7; 88 | 89 | } 90 | .section p { 91 | } 92 | 93 | #main p { 94 | } 95 | 96 | td.product { 97 | text-align: left; 98 | } 99 | td.price { 100 | text-align: center; 101 | } 102 | td.order { 103 | text-align: center; 104 | } 105 | 106 | a img { 107 | border: none; 108 | } 109 | 110 | .topmenu { 111 | border: 1px dotted green; 112 | padding-left: 1%; 113 | margin-top: 1%; 114 | margin-bottom: 1%; 115 | font-size: 110%; 116 | font-weight: bold; 117 | background-color: #bedaf2; 118 | width: 98.9%; 119 | display: block; 120 | position: relative; 121 | } 122 | 123 | .topmenu ol { 124 | border1: 1px dotted blue; 125 | display: inline; 126 | padding: 0; 127 | margin: 0; 128 | float: left; 129 | } 130 | .topmenu li { 131 | display: inline; 132 | border: 1px solid #8eaac2; 133 | margin: 0; 134 | padding1: 0.3em 0.8em; 135 | padding: 0; 136 | background-color: #9ebad2; 137 | list-style: none; 138 | float: left; 139 | } 140 | .topmenu a:visited, .topmenu a:link, .topmenu a:active { 141 | color: #3e5a72; 142 | text-decoration: none; 143 | } 144 | .topmenu a:hover { 145 | color: #3e5a72; 146 | text-decoration: underline; 147 | } 148 | 149 | 150 | 151 | .floatmenu { 152 | border: 1px solid #bedaf2; 153 | font-size: 110%; 154 | font-weight: bold; 155 | background-color1: #bedaf2; 156 | background-color: white; 157 | display: block; 158 | margin: 2.5em 10px 4px 10px; 159 | padding: 4px; 160 | float: right; 161 | } 162 | 163 | .floatmenu ol { 164 | border1: 1px dotted blue; 165 | display: block; 166 | padding: 0; 167 | margin: 0; 168 | } 169 | .floatmenu li { 170 | display: block; 171 | border: 2px solid ; 172 | border-color: #bedaf2 #7e9ab2 #7e9ab2 #bedaf2; 173 | margin: 0.3em 0.4em; 174 | background-color: #9ebad2; 175 | padding: 0.2em 0.6em; 176 | list-style: none; 177 | text-align: center; 178 | } 179 | .floatmenu a:visited, .floatmenu a:link, .floatmenu a:active { 180 | color: #3e5a72; 181 | text-decoration: none; 182 | } 183 | .floatmenu a:hover { 184 | color: #3e5a72; 185 | text-decoration: underline; 186 | } 187 | 188 | .floatmenu, .topmenu { 189 | font-family: Tahoma; 190 | } 191 | 192 | 193 | div.download { 194 | margin: 0.3em; 195 | padding: 0.3em; 196 | border: solid 1px #bedaf2; 197 | width: auto; 198 | color: #3e5a72; 199 | float1: left; 200 | } 201 | 202 | table.download { 203 | border: solid 1px green; 204 | font-weight: bold; 205 | margin-left: 0.5em; 206 | background1: #CCFFCC; 207 | } 208 | 209 | .download td { 210 | border: 1px solid #00CC00; 211 | padding: 10px; 212 | vertical-align: middle; 213 | } 214 | 215 | .download td, .download a:visited, .download a:link, .download a:active { 216 | color1: #3e5a72; 217 | color: #3e725a; 218 | text-decoration: none; 219 | } 220 | .download a:hover { 221 | color1: #3e5a72; 222 | color: #3e725a; 223 | text-decoration: underline; 224 | } 225 | .download td.icon { 226 | background: url(downg.png) no-repeat right center; 227 | padding-right: 0; 228 | } 229 | .download td.icon a { 230 | padding-right: 32px; 231 | margin-right: 0; 232 | border1: 1px solid red; 233 | } 234 | 235 | pre.pb { 236 | margin-left: 0.3em; 237 | padding: 0.3em; 238 | background-color1: #ccd6e0; 239 | background-color: #ffffee; 240 | border: 1px solid #ccd6e0; 241 | } 242 | pre { 243 | margin-left: 0.3em; 244 | padding: 0.3em; 245 | } 246 | 247 | .cmt { 248 | color: #5e7a92; 249 | } 250 | 251 | -------------------------------------------------------------------------------- /pbsrc/Samples/BrowseForFolder/debug/1: -------------------------------------------------------------------------------- 1 | Comparing files libPBInvoke.dll and LIBPBINVOKE.1 2 | 0005C168: 39 36 3 | 0005C169: 38 34 4 | 0005C16A: 65 35 5 | 0005C16C: 65 62 6 | 0005C16D: 62 30 7 | 0005C16E: 38 33 8 | 0005C16F: 66 32 9 | 0005C170: 36 63 10 | 0005C171: 33 31 11 | 0005C172: 30 39 12 | 0005C173: 30 37 13 | 0005C175: 30 61 14 | 0005C176: 33 36 15 | 0005C177: 62 36 16 | 0005C178: 35 39 17 | 0005C179: 37 31 18 | 0005C17A: 37 38 19 | 0005C17B: 38 62 20 | 0005C17C: 32 33 21 | 0005C17D: 64 39 22 | 0005C17E: 62 61 23 | 0005C17F: 64 33 24 | 0005C180: 30 31 25 | 0005C181: 33 35 26 | 0005C182: 30 64 27 | 0005C183: 62 33 28 | 0005C185: 37 31 29 | 0005C186: 64 37 30 | 0005C187: 61 39 31 | 0005C188: 34 30 32 | 0005C189: 33 38 33 | 0005C18A: 63 37 34 | 0005C18D: 38 37 35 | 0005C18E: 33 64 36 | 0005C190: 37 64 37 | 0005C191: 35 61 38 | 0005C192: 30 64 39 | 0005C193: 32 62 40 | 0005C194: 38 39 41 | 0005C195: 36 34 42 | 0005C196: 32 30 43 | 0005C197: 63 62 44 | 0005C198: 39 38 45 | 0005C199: 34 31 46 | 0005C19A: 38 30 47 | 0005C19B: 31 62 48 | 0005C19C: 65 32 49 | 0005C19D: 32 36 50 | 0005C19E: 62 63 51 | 0005C19F: 34 62 52 | 0005C1A0: 36 30 53 | 0005C1A1: 30 31 54 | 0005C1A3: 33 65 55 | 0005C1A4: 62 32 56 | 0005C1A5: 39 62 57 | 0005C1A6: 34 66 58 | 0005C1A7: 66 39 59 | 0005C1A8: 33 30 60 | 0005C1A9: 36 65 61 | 0005C1AB: 39 34 62 | 0005C1AC: 36 61 63 | 0005C1AD: 63 66 64 | 0005C1AE: 34 63 65 | 0005C1AF: 35 63 66 | 0005C1B0: 38 39 67 | 0005C1B1: 33 66 68 | 0005C1B2: 37 30 69 | 0005C1B3: 34 65 70 | 0005C1B5: 38 66 71 | 0005C1B6: 61 34 72 | 0005C1B7: 30 33 73 | 0005C1B8: 37 35 74 | 0005C1B9: 35 66 75 | 0005C1BA: 66 36 76 | 0005C1BB: 34 36 77 | 0005C1BC: 38 61 78 | 0005C1BD: 39 66 79 | 0005C1BE: 30 65 80 | 0005C1BF: 62 31 81 | 0005C1C0: 33 62 82 | 0005C1C1: 66 64 83 | 0005C1C2: 34 65 84 | 0005C1C3: 37 32 85 | 0005C1C4: 65 66 86 | 0005C1C5: 31 65 87 | 0005C1C6: 39 31 88 | 0005C1C7: 34 65 89 | 0005C1C8: 38 31 90 | 0005C1CA: 36 39 91 | 0005C1CB: 31 30 92 | 0005C1CC: 65 66 93 | 0005C1CD: 31 38 94 | 0005C1CE: 33 31 95 | 0005C1CF: 66 64 96 | 0005C1D1: 61 32 97 | 0005C1D2: 37 34 98 | 0005C1D3: 35 61 99 | 0005C1D4: 39 61 100 | 0005C1D5: 35 38 101 | 0005C1D6: 37 62 102 | 0005C1D7: 36 38 103 | 0005C1D8: 31 30 104 | 0005C1D9: 66 34 105 | 0005C1DA: 61 36 106 | 0005C1DB: 30 35 107 | 0005C1DC: 66 64 108 | 0005C1DE: 64 61 109 | 0005C1DF: 32 39 110 | 0005C1E0: 33 61 111 | 0005C1E1: 35 33 112 | 0005C1E2: 31 35 113 | 0005C1E3: 61 39 114 | 0005C1E4: 37 32 115 | 0005C1E5: 33 35 116 | 0005C1E6: 64 34 117 | 0005C1E7: 66 33 118 | 0005C1EA: 61 31 119 | 0005C1EB: 64 31 120 | 0005C1ED: 61 66 121 | 0005C1EE: 31 63 122 | 0005C1EF: 35 39 123 | 0005C1F1: 33 39 124 | 0005C1F2: 62 63 125 | 0005C1F3: 65 34 126 | 0005C1F4: 39 33 127 | 0005C1F6: 39 63 128 | 0005C1F7: 30 34 129 | 0005C1F8: 33 66 130 | 0005C1F9: 62 30 131 | 0005C1FA: 66 34 132 | 0005C1FC: 39 35 133 | 0005C1FD: 36 31 134 | 0005C1FE: 34 64 135 | 0005C1FF: 65 38 136 | 0005C200: 39 33 137 | 0005C201: 39 33 138 | 0005C202: 30 65 139 | 0005C203: 34 31 140 | 0005C204: 65 35 141 | 0005C205: 64 38 142 | 0005C206: 61 64 143 | 0005C207: 31 30 144 | 0005C208: 66 34 145 | 0005C209: 34 33 146 | 0005C20A: 65 36 147 | 0005C20B: 62 39 148 | 0005C20C: 64 61 149 | 0005C20D: 36 63 150 | 0005C20E: 31 35 151 | 0005C20F: 33 31 152 | 0005C210: 66 39 153 | 0005C211: 39 62 154 | 0005C212: 35 34 155 | 0005C213: 32 37 156 | 0005C214: 34 32 157 | 0005C215: 35 38 158 | 0005C216: 33 31 159 | 0005C217: 64 66 160 | 0005C218: 61 36 161 | 0005C219: 39 63 162 | 0005C21A: 31 61 163 | 0005C21B: 61 62 164 | 0005C21D: 31 35 165 | 0005C21E: 30 34 166 | 0005C21F: 38 39 167 | 0005C220: 64 66 168 | 0005C221: 34 31 169 | 0005C222: 65 37 170 | 0005C223: 32 38 171 | 0005C224: 38 66 172 | 0005C225: 32 64 173 | 0005C226: 64 30 174 | 0005C228: 34 61 175 | 0005C229: 38 37 176 | 0005C22A: 38 34 177 | 0005C22B: 39 66 178 | 0005C22C: 37 61 179 | 0005C22D: 36 34 180 | 0005C22F: 65 63 181 | 0005C230: 39 33 182 | 0005C231: 33 38 183 | 0005C232: 31 30 184 | 0005C233: 64 35 185 | 0005C234: 30 33 186 | 0005C235: 31 33 187 | 0005C236: 39 64 188 | 0005C237: 63 62 189 | 0005C238: 35 62 190 | 0005C239: 63 62 191 | 0005C23A: 30 39 192 | 0005C23B: 31 33 193 | 0005C23C: 66 30 194 | 0005C23D: 31 63 195 | 0005C23E: 32 35 196 | 0005C23F: 66 38 197 | 0005C240: 61 64 198 | 0005C241: 39 64 199 | 0005C242: 61 34 200 | 0005C243: 36 61 201 | 0005C244: 33 61 202 | 0005C245: 34 31 203 | 0005C246: 63 31 204 | 0005C247: 34 33 205 | 0005C248: 61 66 206 | 0005C249: 65 34 207 | 0005C24A: 64 39 208 | 0005C24B: 65 34 209 | 0005C24C: 65 34 210 | 0005C24D: 66 65 211 | 0005C24E: 64 61 212 | 0005C24F: 33 62 213 | 0005C250: 30 66 214 | 0005C251: 62 39 215 | 0005C252: 38 61 216 | 0005C253: 33 32 217 | 0005C254: 32 37 218 | 0005C255: 33 66 219 | 0005C256: 62 65 220 | 0005C257: 33 39 221 | 0005C258: 36 34 222 | 0005C259: 30 64 223 | 0005C25A: 32 65 224 | 0005C25B: 61 37 225 | 0005C25C: 61 31 226 | 0005C25D: 34 35 227 | 0005C25E: 33 62 228 | 0005C260: 36 39 229 | 0005C261: 37 32 230 | 0005C262: 61 39 231 | 0005C263: 66 30 232 | 0005C264: 37 35 233 | 0005C265: 38 63 234 | 0005C267: 37 33 235 | 0005C268: 38 61 236 | 0005C269: 36 34 237 | 0005D1D1: 32 30 238 | 0005D1D6: 33 31 239 | -------------------------------------------------------------------------------- /src/CallbackData.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "DynCallback.h" 3 | 4 | using namespace std; 5 | 6 | CallbackData::CallbackData(int argc, bool stdCall) 7 | { 8 | m_argc = argc; 9 | char *fnBuf = (char *)&thunk_templ; 10 | //printf("fnBuf=%p\n", fnBuf); 11 | if (fnBuf[0] == '\xE9') { 12 | // debug thunk - need to follow jumps to find real fn body 13 | int offset = *(int*)&fnBuf[1]; 14 | //printf("jmp %X\n", offset); 15 | fnBuf += offset + 5 /* 1 + 4 bytes for jmp OFFSET */; 16 | } 17 | char *fnBufEnd = (char *)memchr(fnBuf, '\xC2' /*RET xxx*/, 2048 /*max template size */); 18 | if (fnBufEnd == NULL) { 19 | throw InvalidCallbackTemplateException("end of function not found"); 20 | } 21 | size_t fnSize = fnBufEnd - fnBuf + 3; 22 | //printf("fnSize=%i\n", fnSize); 23 | 24 | m_thunk.resize(fnSize); 25 | memcpy(&m_thunk[0], fnBuf, m_thunk.size()); 26 | 27 | 28 | //dump(); 29 | 30 | // correct RET xxx (last 3 bytes of fn body, C2 04 00) 31 | if (m_argc == 0 && !stdCall /* cdecl, caller must clear stack*/) { 32 | m_thunk[m_thunk.size() - 3] = (BYTE)0xC3; // RET 0 33 | } 34 | else { 35 | *((unsigned short*)&m_thunk[m_thunk.size() - 2]) = (unsigned short)m_argc * 4; // RET XXX, XXX > 0 36 | } 37 | 38 | // correct 'this' reference 39 | adjustConstant(THIS_MARKER, (DWORD)this); 40 | 41 | // correct real callback reference 42 | adjustConstant(CALLBACK_MARKER, (DWORD)&staticCallback); 43 | 44 | DWORD oldProtect; 45 | BOOL ret = VirtualProtect(&m_thunk[0], m_thunk.size(), PAGE_EXECUTE_READWRITE, &oldProtect); 46 | 47 | //dump(); 48 | 49 | } 50 | 51 | CallbackData::~CallbackData() 52 | { 53 | 54 | } 55 | 56 | int CALLBACK CallbackData::thunk_templ(int dummy) 57 | { 58 | DWORD *argsPtr = (DWORD *) &dummy; 59 | int (CALLBACK *ptr)(DWORD, DWORD *) = (int (CALLBACK*)(DWORD, DWORD *)) CALLBACK_MARKER; 60 | return ptr(THIS_MARKER, argsPtr); 61 | } 62 | 63 | DWORD CallbackData::getCallbackAddr() 64 | { 65 | return (DWORD)&m_thunk[0]; 66 | } 67 | 68 | int CallbackData::runCallback() 69 | { 70 | int (CALLBACK *ptr)() = (int (CALLBACK *)()) getCallbackAddr(); 71 | int save1, save2; 72 | __asm { 73 | mov save1, esp; 74 | } 75 | int res = ptr(); 76 | __asm { 77 | mov save2, esp; 78 | } 79 | printf("save1=%p, save2=%p\n", save1, save2); 80 | return res; 81 | } 82 | int CallbackData::runCallback(int arg1) 83 | { 84 | int (CALLBACK *ptr)(int) = (int (CALLBACK *)(int)) getCallbackAddr(); 85 | int save1, save2; 86 | __asm { 87 | mov save1, esp; 88 | } 89 | int res = ptr(arg1); 90 | __asm { 91 | mov save2, esp; 92 | } 93 | printf("save1=%p, save2=%p\n", save1, save2); 94 | return res; 95 | } 96 | 97 | int CallbackData::runCallback(int arg1, int arg2) 98 | { 99 | int (CALLBACK *ptr)(int, int) = (int (CALLBACK *)(int, int)) getCallbackAddr(); 100 | int save1, save2; 101 | __asm { 102 | mov save1, esp; 103 | } 104 | int res = ptr(arg1, arg2); 105 | __asm { 106 | mov save2, esp; 107 | } 108 | printf("save1=%p, save2=%p\n", save1, save2); 109 | return res; 110 | } 111 | 112 | 113 | 114 | void CallbackData::dump() 115 | { 116 | for (int i = 0; i < m_thunk.size(); i ++) { 117 | printf("%02X ", (BYTE)m_thunk[i]); 118 | } 119 | printf("\n"); 120 | } 121 | 122 | std::string CallbackData::dumpThunk() 123 | { 124 | vector buf; 125 | buf.resize(m_thunk.size() * 3 ); 126 | for (int i = 0; i < m_thunk.size(); i ++) { 127 | sprintf(&buf[i * 3], "%02X ", (BYTE)m_thunk[i]); 128 | } 129 | buf.push_back('\0'); 130 | return &buf[0]; 131 | } 132 | 133 | 134 | void CallbackData::adjustConstant(DWORD marker, DWORD newValue) 135 | { 136 | for (int i = 0; i < m_thunk.size() - 4; i ++) { 137 | if (*(DWORD*)&m_thunk[i] == marker) { 138 | *(DWORD*)&m_thunk[i] = newValue; 139 | return; 140 | } 141 | } 142 | throw InvalidCallbackTemplateException("marker not found"); 143 | } 144 | 145 | int CALLBACK CallbackData::staticCallback(CallbackData * thisPtr, DWORD *argsPtr) 146 | { 147 | thisPtr->m_argsPtr = argsPtr; 148 | return thisPtr->callback(); 149 | } 150 | 151 | int CALLBACK CallbackData::callback() 152 | { 153 | return 1; 154 | } 155 | 156 | 157 | typedef DWORD (*DWORDMethod)(); 158 | DWORD runDynamicMethod(DWORD addr, DWORD *argv, int argc, bool isStdCall) { 159 | DWORDMethod method = (DWORDMethod)addr; 160 | for (int i = argc - 1; i >= 0; i --) { 161 | DWORD arg = argv[i]; 162 | __asm push arg; 163 | } 164 | DWORD ret = method(); 165 | if (!isStdCall) { 166 | int argsSize = argc * sizeof(DWORD); 167 | __asm add esp, argsSize; 168 | } 169 | return ret; 170 | } 171 | 172 | typedef double (*DoubleMethod)(DWORD, DWORD *, int, bool); 173 | double runDynamicDoubleMethod(DWORD addr, DWORD *argv, int argc, bool isStdCall) { 174 | DoubleMethod method = (DoubleMethod) &runDynamicMethod; 175 | return method(addr, argv, argc, isStdCall); 176 | } 177 | 178 | 179 | typedef float (*FloatMethod)(DWORD, DWORD *, int, bool); 180 | float runDynamicFloatMethod(DWORD addr, DWORD *argv, int argc, bool isStdCall) { 181 | FloatMethod method = (FloatMethod) &runDynamicMethod; 182 | return method(addr, argv, argc, isStdCall); 183 | } 184 | 185 | typedef __int64 (*Int64Method)(DWORD, DWORD *, int, bool); 186 | __int64 runDynamicInt64Method(DWORD addr, DWORD *argv, int argc, bool isStdCall) { 187 | Int64Method method = (Int64Method) &runDynamicMethod; 188 | return method(addr, argv, argc, isStdCall); 189 | } -------------------------------------------------------------------------------- /src/parser/ASTNode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../types/Basetype.h" 5 | #include 6 | #include "../Compiler.h" 7 | #include "../Runtime.h" 8 | #include "../Core.h" 9 | using namespace std; 10 | 11 | enum { 12 | ATTR_SIGNED = 1 << 0, 13 | ATTR_UNSIGNED = 1 << 1, 14 | ATTR_CHAR = 1 << 2, 15 | ATTR_INT8 = 1 << 3, 16 | ATTR_WCHAR_T = 1 << 4, 17 | ATTR_SHORT = 1 << 5, 18 | ATTR_INT16 = 1 << 6, 19 | ATTR_INT = 1 << 7, 20 | ATTR_INT32 = 1 << 8, 21 | ATTR_LONG = 1 << 9, 22 | ATTR_INT64 = 1 << 10, 23 | ATTR_LONGLONG = 1 << 11, 24 | ATTR_DOUBLE = 1 << 12, 25 | ATTR_FLOAT = 1 << 13, 26 | ATTR_VOID = 1 << 14, 27 | ATTR_COUNT = 15, 28 | }; 29 | 30 | struct ASTPtrTypeOp; 31 | struct ASTRefTypeOp; 32 | struct ASTDeclaratorId; 33 | struct ASTNodeList; 34 | struct ASTMethodTypeOp; 35 | struct ASTDeclarator; 36 | struct ASTStructType; 37 | struct ASTArrayTypeOp; 38 | 39 | struct IASTNode { 40 | virtual ~IASTNode() {} 41 | virtual int getTypeId() { return ASTNodeId; } 42 | 43 | inline ASTNodeList* getNodeList() { return (ASTNodeList*)this; } 44 | inline ASTPtrTypeOp* getPtrTypeOp() { return (ASTPtrTypeOp*)this; } 45 | inline ASTRefTypeOp* getRefTypeOp() { return (ASTRefTypeOp*)this; } 46 | inline ASTDeclaratorId* getDeclaratorId() { return (ASTDeclaratorId*)this; } 47 | inline ASTMethodTypeOp* getMethodTypeOp() { return (ASTMethodTypeOp*)this; } 48 | inline ASTDeclarator* getDeclarator() { return (ASTDeclarator*)this; } 49 | inline ASTStructType* getStructType() { return (ASTStructType*)this; } 50 | virtual void setTypeAttr(int attr) { throw RuntimeException("Internal error: illegal use of type attributes"); } 51 | virtual Type getTypeRef() { throw RuntimeException("Internal error: illegal use of type reference"); } 52 | 53 | protected: 54 | enum { 55 | ASTNodeId, 56 | ASTPtrTypeOpId, 57 | ASTRefTypeOpId, 58 | ASTDeclaratorIdId, 59 | ASTNodeListId, 60 | ASTMethodTypeOpId, 61 | ASTArrayTypeOpId, 62 | }; 63 | }; 64 | 65 | typedef boost::shared_ptr ASTNode; 66 | 67 | struct ASTDeclarator: public IASTNode { 68 | virtual void convert(Type typeRef, NamedType& namedType) = 0; 69 | virtual void setStdCall(bool _isStdCall) = 0; 70 | virtual bool getStdCall() = 0; 71 | }; 72 | 73 | struct ASTPtrTypeOp: public ASTDeclarator { 74 | ASTNode arg; 75 | ASTPtrTypeOp(ASTNode _arg) : arg(_arg) {} 76 | virtual int getTypeId() { return ASTPtrTypeOpId; } 77 | virtual void setStdCall(bool _isStdCall) {arg->getDeclarator()->setStdCall(_isStdCall);} 78 | virtual bool getStdCall() {return arg->getDeclarator()->getStdCall();} 79 | virtual void convert(Type typeRef, NamedType& namedType); 80 | }; 81 | 82 | struct ASTRefTypeOp: public ASTDeclarator { 83 | ASTNode arg; 84 | ASTRefTypeOp(ASTNode _arg) : arg(_arg) {} 85 | virtual int getTypeId() { return ASTRefTypeOpId; } 86 | virtual void setStdCall(bool _isStdCall) {arg->getDeclarator()->setStdCall(_isStdCall);} 87 | virtual bool getStdCall() {return arg->getDeclarator()->getStdCall();} 88 | virtual void convert(Type typeRef, NamedType& namedType); 89 | }; 90 | 91 | struct ASTDeclaratorId: public ASTDeclarator { 92 | bool isStdCall; 93 | string id; 94 | ASTDeclaratorId(const string& _id) : id(_id), isStdCall(CoreInstance.getDefCallingConvention()) {} 95 | virtual int getTypeId() { return ASTDeclaratorIdId; } 96 | virtual void setStdCall(bool _isStdCall) { isStdCall = _isStdCall; }; 97 | virtual bool getStdCall() { return isStdCall;} 98 | virtual void convert(Type typeRef, NamedType& namedType); 99 | }; 100 | 101 | struct ASTNodeList: public IASTNode { 102 | vector list; 103 | ASTNodeList(ASTNode _node) { list.push_back(_node); } 104 | ASTNodeList() { } 105 | virtual int getTypeId() { return ASTNodeListId; } 106 | void typeDef(Type typeRef, Compiler& compiler); 107 | void nameDef(Type typeRef, Compiler& compiler); 108 | void nameDef(Type typeRef, vector &names, Compiler& compiler); 109 | }; 110 | 111 | struct ASTMethodTypeOp: public ASTDeclarator { 112 | bool isStdCall; 113 | vector params; 114 | ASTNode id; 115 | ASTMethodTypeOp(ASTNode _id, vector& _params): params(_params), isStdCall(CoreInstance.getDefCallingConvention()), id(_id) { } 116 | virtual void setStdCall(bool _isStdCall) { isStdCall = _isStdCall; } 117 | virtual bool getStdCall() { return isStdCall;} 118 | virtual int getTypeId() { return ASTMethodTypeOpId; } 119 | virtual void convert(Type typeRef, NamedType& namedType); 120 | }; 121 | 122 | struct ASTStructType: public IASTNode { 123 | string name; 124 | Type structType; 125 | Compiler &compiler; 126 | ASTStructType(const string& _name, Compiler &_compiler); 127 | void completeStruct(int structTypeId, vector &_fields); 128 | void forwardDecl(); 129 | virtual Type getTypeRef(); 130 | }; 131 | 132 | struct ASTInternalType: public IASTNode { 133 | int attrs; 134 | Compiler &compiler; 135 | ASTInternalType(Compiler &_compiler); 136 | virtual void setTypeAttr(int attr); 137 | virtual Type getTypeRef(); 138 | static string getInternalTypeName(int attr); 139 | }; 140 | struct ASTUserType: public IASTNode { 141 | string name; 142 | Compiler &compiler; 143 | ASTUserType(const string& _name, Compiler &_compiler); 144 | virtual Type getTypeRef(); 145 | }; 146 | 147 | struct ASTArrayTypeOp: public ASTDeclarator { 148 | ASTNode m_arg; 149 | int m_bound; 150 | bool m_isParam; 151 | ASTArrayTypeOp(ASTNode arg, int bound, bool isParam) 152 | : m_arg(arg), m_bound(bound), m_isParam(isParam) {} 153 | virtual int getTypeId() { return ASTArrayTypeOpId; } 154 | virtual void setStdCall(bool isStdCall) {m_arg->getDeclarator()->setStdCall(isStdCall);} 155 | virtual bool getStdCall() {return m_arg->getDeclarator()->getStdCall();} 156 | virtual void convert(Type typeRef, NamedType& namedType); 157 | }; 158 | 159 | -------------------------------------------------------------------------------- /doc/genhelp/working-with-structures.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Working with C/C++ structures/unions 4 | 5 | 6 | 7 |
    8 | 11 |

    Working with C/C++ structures/unions

    12 | 13 |

    PBInvoke supports full access to C++ structs/unions from PowerBuilder. 14 | 15 |

    Because there is no equivalents for unions and field types such 16 | as pointers to structures and function pointers in PowerBuilder, 17 | PBInvoke have a special object for storing such values: n_pi_value. 18 | 19 |

    Working with nested structures and unions.

    20 |

    Suppose you have the following structure declaration: 21 |

    n_pi_core lnv_core
     22 | lnv_core.of_declare("struct MYSTR { union { int ival; char* sval;} u; char ch;}")
     23 | 
    24 | This is a structure MYSTR which has a field of type char, 'ch', and a field of type union 'u', 25 | which itself has two fields 'ival' and 'sval', which share the same memory. 26 | 27 |

    Some examples of working with the structure: 28 |

    n_pi_core lnv_core
     29 | n_pi_value lnv_str
     30 | 
     31 | // Create an instance of the structure in memory
     32 | // In C++: MYSTR str;
     33 | lnv_str = lnv_core.of_create_value_of("MYSTR"); 
     34 | 
     35 | // Fill the structure's memory with zero bytes.
     36 | // Note, however, that of_create_value_of() does it anyway.
     37 | // C++: memset(&str, sizeof(MYSTR), 0);
     38 | lnv_str.of_set(0)
     39 | 
     40 | // Assign to sval field of the union
     41 | // C++: str.u.sval = "test";
     42 | lnv_str.of_item("u").of_set("sval", "test")
     43 | 
    44 | A few words regarding what does n_pi_value.of_item do. 45 | When you call of_item("fieldname"), a n_pi_value is returned which is a reference to the field. 46 | No data is copied. When you modify this reference, the original structure is modified. 47 |

    of_item() is used most often for accessing nested structures. 48 | If you have a field of a simple type (string, numeric) you use of_get("field")/of_set("field", value) 49 | instead of of_item("field"). 50 |

    Also note, that field name in of_item(), of_get(), of_set() is case sensitive. 51 |

    // Read the value of ival which now holds the pointer to the string "test" because ival and sval share their memory.
     52 | // C++: int i = str.u.ival;
     53 | ll_i = lnv_str.of_item("u").of_get("ival")
     54 | 
     55 | // Assign to ch field of the structure
     56 | // C++: str.ch = 'A';
     57 | lnv_str.of_set("ch", "A")
     58 | lnv_str.of_set(2, "A") // Fields can also be accessed by a 1-based index in order of their declarations.
     59 | 
     60 | // Pass the structure as a parameter to a function:
     61 | // C++: void fn1(MYSTR s) { }  
     62 | //      fn1(str) 
     63 | n_pi_method lnv_fn1
     64 | lnv_fn1 = lnv_somedll.of_declare_method("void fn1(MYSTR s)")
     65 | lnv_fn1.of_invoke(lnv_str) // lnv_str's value is copied.
     66 | 
     67 | // Pass the structure as a pointer parameter to a function:
     68 | // C++: void fn2(MYSTR *s) { s->u.sval = "fn2"; };  
     69 | //      fn2(&str) 
     70 | lnv_fn2 = lnv_somedll.of_declare_method("void fn2(MYSTR *s)")
     71 | lnv_fn2.of_invoke(lnv_str) // implicitly gets the address of the structure
     72 | //or
     73 | lnv_fn2.of_invoke(lnv_str.of_get_addr()) // which is the same, but explicit.
     74 | 
     75 | // If the structure is modified in fn2 we'll see those changes
     76 | String ls_mod
     77 | ls_mod = lnv_str.of_item("u").of_get("sval") // returns "fn2"
     78 | 
     79 | 
    80 | 81 |

    Working with pointers to structures as fields.

    82 | Pointers to a type require dereferencing in order to allow access to the value they point to. 83 | 84 |
    lnv_core.of_declare("struct N { int a;}")  // declare a struct
     85 | lnv_core.of_declare("struct S { N* n;}")   // declare a struct with nested pointer to a struct
     86 | // create an instance
     87 | // C++: S str;
     88 | lnv_str = lnv_core.of_create_value_of("S")
     89 | 
     90 | // init the pointer n with the address of an instance of N
     91 | // C++: s.n = new N();
     92 | lnv_str.of_set("n", lnv_core.of_create_value_of("N"))
     93 | 
     94 | // access the nested field, a
     95 | // C++:  str.n->a = 123;
     96 | lnv_str.of_item("n").of_deref().of_set("a", 123)
     97 | 
     98 | // get the nested structure as separate reference
     99 | // C++: N &n = *str.n;
    100 | lnv_n = lnv_str.of_item("n").of_deref() // note this is just a reference, not a copy.
    101 | 
    102 | //Now lnv_n.of_get("a") is the same as lnv_str.of_item("n").of_deref().of_get("a")
    103 | 
    104 | 105 |

    See also

    106 |
  • Handling strings (char*, wchar_t*) 107 |
  • Handling TCHAR and TSTR. Unicode/ANSI function name suffixes 108 |
  • Working with callbacks 109 | 110 | 111 | 112 | 113 | 114 | 115 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /src/parser/ASTNode.cpp: -------------------------------------------------------------------------------- 1 | #include "../stdafx.h" 2 | #include "ASTNode.h" 3 | 4 | #include "../types/PointerType.h" 5 | #include "../types/RefType.h" 6 | #include "../types/MethodType.h" 7 | #include "../types/StructType.h" 8 | #include "../types/ArrayType.h" 9 | #include "../Core.h" 10 | 11 | //typedef int iii; 12 | //typedef int iii; 13 | 14 | int __cdecl fn1(); 15 | int *__cdecl fn2(); 16 | int ( __cdecl * fn3)(); 17 | //int ( * __cdecl fn4)(); //warning C4229: anachronism used : modifiers on data are ignored 18 | //typedef __declspec(align(1)) struct S1 {}; //warning C4091: 'typedef ' : ignored on left of 'S1' when no variable is declared 19 | //__declspec(align(1)) struct S2 {}; 20 | 21 | 22 | void ASTDeclaratorId::convert(Type typeRef, NamedType& namedType) 23 | { 24 | namedType.name = id; 25 | namedType.type = typeRef; 26 | } 27 | 28 | void ASTPtrTypeOp::convert(Type typeRef, NamedType& namedType) 29 | { 30 | arg->getDeclarator()->convert(Type(new PointerType(typeRef)), namedType); 31 | } 32 | 33 | void ASTRefTypeOp::convert(Type typeRef, NamedType& namedType) 34 | { 35 | arg->getDeclarator()->convert(Type(new RefType(typeRef)), namedType); 36 | } 37 | 38 | void ASTArrayTypeOp::convert(Type typeRef, NamedType& namedType) 39 | { 40 | if (/*m_bound == 0 ||*/ m_isParam) { 41 | typeRef = Type(new PointerType(typeRef)); 42 | } 43 | else { 44 | typeRef = Type(new ArrayType(typeRef, m_bound)); 45 | } 46 | m_arg->getDeclarator()->convert(typeRef, namedType); 47 | } 48 | 49 | 50 | void ASTMethodTypeOp::convert(Type typeRef, NamedType& namedType) 51 | { 52 | Type methodType = Type(new MethodType(typeRef, params, isStdCall)); 53 | id->getDeclarator()->convert(methodType, namedType); 54 | } 55 | 56 | void ASTNodeList::typeDef(Type typeRef, Compiler& compiler) 57 | { 58 | for (size_t i = 0; i < list.size(); i ++) { 59 | NamedType namedType; 60 | list[i]->getDeclarator()->convert(typeRef, namedType); 61 | compiler.defineType(namedType.name, namedType.type); 62 | } 63 | } 64 | 65 | 66 | 67 | 68 | void ASTNodeList::nameDef(Type typeRef, Compiler& compiler) 69 | { 70 | for (size_t i = 0; i < list.size(); i ++) { 71 | NamedType namedType; 72 | list[i]->getDeclarator()->convert(typeRef, namedType); 73 | compiler.defineName(namedType.name, namedType.type); 74 | } 75 | } 76 | void ASTNodeList::nameDef(Type typeRef, vector &names, Compiler& compiler) 77 | { 78 | for (size_t i = 0; i < list.size(); i ++) { 79 | NamedType namedType; 80 | list[i]->getDeclarator()->convert(typeRef, namedType); 81 | names.push_back(namedType); 82 | } 83 | } 84 | //void ASTDeclaratorId::setStdCall(bool _isStdCall) 85 | //{ 86 | // throw RuntimeException("Cannot apply " + string(_isStdCall ? "__stdcall":"__cdecl") + 87 | // " to identifier '" + id + "'"); 88 | //} 89 | 90 | 91 | ASTStructType::ASTStructType(const string& _name, Compiler &_compiler) 92 | : name(_name) 93 | , compiler(_compiler) 94 | { 95 | forwardDecl(); 96 | } 97 | 98 | void ASTStructType::completeStruct(int structTypeId, vector &fields) 99 | { 100 | bool isUnion; 101 | if (structTypeId == TC_STRUCT_TYPE) 102 | isUnion = false; 103 | else if (structTypeId == TC_UNION_TYPE) 104 | isUnion = true; 105 | else 106 | throw RuntimeException("Internal error: Uknown struct type ID used: " + string(CUtil::toString(structTypeId))); 107 | 108 | ((StructType*)structType.get())->complete(fields, CoreInstance.getPack(), 0, isUnion); // TODO add align (declspec) 109 | 110 | dprintf("defineStruct, type=%p, sig=%s\n", structType.get(), structType->getTypeSignature("*").c_str()); 111 | structType = compiler.defineType(name, structType); 112 | } 113 | 114 | Type ASTStructType::getTypeRef() 115 | { 116 | return structType; 117 | } 118 | 119 | void ASTStructType::forwardDecl() 120 | { 121 | structType = Type(new StructType(name)); 122 | compiler.defineTag(name, structType); 123 | } 124 | 125 | 126 | ASTInternalType::ASTInternalType(Compiler &_compiler) 127 | : compiler(_compiler) 128 | , attrs (0) 129 | { 130 | 131 | } 132 | void ASTInternalType::setTypeAttr(int attr) 133 | { 134 | attrs = attrs | attr; 135 | } 136 | 137 | 138 | Type ASTInternalType::getTypeRef() 139 | { 140 | return compiler.findType(getInternalTypeName(attrs)); 141 | } 142 | 143 | string ASTInternalType::getInternalTypeName(int attrs) 144 | { 145 | // check check combinations of signed/unsigned 146 | if ((attrs & ATTR_SIGNED) && (attrs & ATTR_UNSIGNED)) 147 | throw RuntimeException("Signed/unsigned keywords mutually exclusive"); 148 | // clear signed/unsigned - it's just ignored 149 | attrs = attrs & (~ (ATTR_SIGNED | ATTR_UNSIGNED)); 150 | 151 | //check combinations of internal types 152 | int currAttr = 1; 153 | int usedAttrs = 0; 154 | for (int i = 0; i < ATTR_COUNT; i ++, currAttr = currAttr << 1) { 155 | if (attrs & currAttr) 156 | usedAttrs ++; 157 | } 158 | if (usedAttrs > 1) 159 | throw RuntimeException("Illegal use of internal types: more than one type specified"); 160 | 161 | // default type: int 162 | if (usedAttrs == 0) 163 | attrs = ATTR_INT; 164 | 165 | // map type implementations 166 | #define MAP_TYPE(s, t) if (attrs & s) { attrs = (attrs | t) & ~s;} 167 | MAP_TYPE(ATTR_INT8, ATTR_CHAR); 168 | MAP_TYPE(ATTR_INT16, ATTR_SHORT); 169 | MAP_TYPE(ATTR_INT32, ATTR_INT); 170 | MAP_TYPE(ATTR_LONG, ATTR_INT); 171 | MAP_TYPE(ATTR_LONGLONG, ATTR_INT64); 172 | 173 | // map attrs to type name 174 | #define MAP_TYPE_NAME(s, t) case s: typeName = t; break; 175 | string typeName; 176 | switch (attrs) { 177 | MAP_TYPE_NAME(ATTR_VOID, "void") 178 | MAP_TYPE_NAME(ATTR_CHAR, "char") 179 | MAP_TYPE_NAME(ATTR_WCHAR_T, "wchar_t") 180 | MAP_TYPE_NAME(ATTR_INT8, "__int8") 181 | MAP_TYPE_NAME(ATTR_INT16, "__int16") 182 | MAP_TYPE_NAME(ATTR_SHORT, "short") 183 | MAP_TYPE_NAME(ATTR_INT, "int") 184 | MAP_TYPE_NAME(ATTR_LONG, "long") 185 | MAP_TYPE_NAME(ATTR_INT32, "__int32") 186 | MAP_TYPE_NAME(ATTR_INT64, "__int64") 187 | MAP_TYPE_NAME(ATTR_LONGLONG, "longlong") 188 | MAP_TYPE_NAME(ATTR_FLOAT, "float") 189 | MAP_TYPE_NAME(ATTR_DOUBLE, "double") 190 | default: 191 | throw RuntimeException("Internal error: unknown type attr " + string(CUtil::toString(attrs))); 192 | } 193 | return typeName; 194 | } 195 | 196 | ASTUserType::ASTUserType(const string& _name, Compiler &_compiler) 197 | : name(_name) 198 | , compiler(_compiler) 199 | { 200 | 201 | } 202 | 203 | Type ASTUserType::getTypeRef() 204 | { 205 | return compiler.findType(name); 206 | } 207 | 208 | -------------------------------------------------------------------------------- /doc/working-with-callbacks.html: -------------------------------------------------------------------------------- 1 |

    Working with callbacks

    2 | 3 |

    PowerBuilder does not support PowerScript code to be directly called from external functions. 4 | 5 |

    As of PB9 there is a possibility to write a C++ extension for that task using PBNI. 6 | However, implementing callbacks using PBNI has the following limitations: 7 |

  • PBNI requires knowledge of C++ from PowerBuilder developer 8 |
  • PBNI extensions are quite hard to write and debug. 9 |
  • PBNI requires separate DLLs for ANSI and Unicode versions. 10 |
  • PBNI is available only as of PB9. 11 |

    Also, there are additional limitations not related to PBNI. 12 |

  • It's hard to implement (even in C++) passing of context data to the callback if the caller does not support that. 13 |
  • A charset conversion is needed when the caller is ANSI and PB is Unicode and vice versa. 14 | 15 |

    PBInvoke has support for declaring and using callbacks directly in PowerScript code 16 | without these limitations. 17 | 18 |

    Callback declaration

    19 |

    In order to declare a callback you need the following steps: 20 |

  • Inherit a custom class from n_pi_method 21 |
  • In the constructor event, call of_declare_callback() with a callback type declaration 22 | or a type name (in case the type was declared earlier). 23 |
  • Extend the ue_callback event 24 | 25 |

    Example: 26 | 27 | // in n_cst_timerproc's constructor (inherited from n_pi_method) 28 | n_pi_core lnv_core 29 | 30 | lnv_core.of_declare("& 31 | typedef VOID CALLBACK TimerProc(& 32 | HWND hwnd, & 33 | UINT uMsg, & 34 | UINT_PTR idEvent, & 35 | DWORD dwTime & 36 | );& 37 | ") 38 | 39 | of_declare_callback("TimerProc") 40 | 41 | 42 | 43 |

    Getting callback address

    44 | Use n_pi_method.of_get_addr() to get the numeric value of the callback address ready to be passed to 45 | an external function which accepts function pointers of this type. 46 | 47 |

    Example: 48 | 49 | n_cst_timerproc lnv_timerproc 50 | lnv_timerproc = Create n_cst_timerproc 51 | 52 | // ef_SetTimer is an external function, alias for WinAPI SetTimer 53 | ll_timer = ef_SetTimer(0, 0, 1000, lnv_timerproc.of_get_addr()) 54 | 55 | 56 | 57 |

    Accessing callback parameters and returning result

    58 | 59 |

    In the ue_callback event, callback parameters can be retrieved by 60 | calling of_get_param("paramname"). 61 | 62 |

    The return value is passed to the caller of the callback using usual RETURN operator. 63 | Note, that PBInvoke does not support the following types as return types of callbacks: 64 |

  • float(real), double 65 |
  • longlong 66 |
  • structs/unions of size of more than 4 bytes 67 |

    However, pointers or references to those type are supported. 68 | 69 |

    Example: 70 | ulong hwnd 71 | ulong uMsg 72 | ulong idEvent 73 | ulong dwTime 74 | 75 | // retrieve parameters 76 | hwnd = of_get_param("hwnd") 77 | uMsg = of_get_param("uMsg") 78 | idEvent = of_get_param("idEvent") 79 | dwTime = of_get_param("dwTime") 80 | 81 | // process event 82 | ... 83 | 84 | Return 0 85 | 86 | 87 |

    Callback context data

    88 |

    All context data needed by a callback can be stored in the instance variables of the callback object 89 | (which is a descendant of n_pi_method). 90 |

    That is possible because PBInvoke generates a unique phisical address (function pointer) for 91 | each callback object, and when an external function calls your callback via that address, PBInvoke maps that call 92 | exactly to your object. 93 | 94 | 95 |

    Performance of callbacks

    96 |

    Marshalling parameters between C++ and PB is a slow operation (compared to PB external functions calls) due to 97 | the flexibility PBInvoke provides. If a PB callback is used as a handler for intercepting GUI messages 98 | (e.g. via calling SetWindowsHookEx), then it may cause slow repaint of UI, or even a hang for a long time, 99 | because UI generates huge amount of messages, most of which are ignored by the callback but take time for marshalling. 100 | 101 |

    PBInvoke provides an optimization for that case. For callbacks used with SetWindowsHookEx WinAPI 102 | function, it's possible to setup a filter for message ID's which are processed by the callback. 103 | If a message ID does not pass the filter, the PowerScript code of the callback will not be called and all the processing 104 | will be done in C++ according to the rules described in MSDN for SetWindowsHookEx hooks: call 105 | CallNextHookEx. 106 |

    In order to activate the message filter you must call of_set_windows_hook_filter() immediately 107 | after calling SetWindowsHookEx(). 108 |

    Syntax:

    109 | 110 | callback.of_set_windows_hook_filter(hook_handle, hook_type, message_id_array[]) 111 | 112 |

    where 113 |

  • callback - callback object 114 |
  • hook_handle - hook handle returned by SetWindowsHookEx() 115 |
  • hook_type - one of supported by PBInvoke hook types (WH_CALLWNDPROCRET, WH_CALLWNDPROC, WH_GETMESSAGE) 116 |
  • message_id_array[] - array of long integers filled with accepted message ID's 117 |
  • 118 | 119 |

    Example: 120 | // This code is part of CustomSaveAs sample, which demonstrates 121 | // using callbacks for customizing Windows Shell 'Save As' dialog. 122 | Long ll_hInstance, ll_hThreadID 123 | 124 | ll_hInstance = inv_GetWindowLong.of_invoke(al_windowhandle, n_pi_winapi.GWL_HINSTANCE) 125 | ll_hThreadID = inv_GetCurrentThreadId.of_invoke() 126 | 127 | il_hHook = inv_SetWindowsHookEx.of_invoke(n_pi_winapi.WH_CALLWNDPROCRET, this.of_get_addr(), ll_hInstance, ll_hThreadID) 128 | 129 | // IMPORTANT! As number of messages sent to UI related windows hooks is really huge, 130 | // processing them all in PowerScript is inefficient, and probably will hang the UI. 131 | // PBInvoke can efficiently filter hook messages by message id. 132 | // The following call enables this feature. 133 | // of_set_windows_hook_filter must be called immediately after SetWindowsHookEx() 134 | // The args: hook handle, hook type, and array of message ids which pass via filter to the hook. 135 | of_set_windows_hook_filter(il_hHook, n_pi_winapi.WH_CALLWNDPROCRET, & 136 | {n_pi_winapi.CB_ADDSTRING, n_pi_winapi.CB_SETCURSEL} ) 137 | 138 | // Currently only WH_CALLWNDPROCRET, WH_CALLWNDPROC, WH_GETMESSAGE hook types are 139 | // supported with this filtering feature 140 | 141 | 142 |

    See also

    143 |
  • Calling DLL functions using PBInvoke 144 | 145 | 146 | -------------------------------------------------------------------------------- /src/Runtime.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma warning (disable:4786) 4 | #include 5 | 6 | #include 7 | 8 | //#include "DataTypes.h" 9 | #include "types/BaseType.h" 10 | #include "types/MethodType.h" 11 | #include "MethodInstance.h" 12 | 13 | using namespace std; 14 | 15 | 16 | class ParamStorage; 17 | class IRuntimeExceptionRegistry; 18 | 19 | class RuntimeException 20 | { 21 | public: 22 | string formatErrorMessage(const string &prefix, const string &suffix, DWORD error); 23 | RuntimeException(const string &msg = "", DWORD lastOsError = 0); 24 | RuntimeException(IRuntimeExceptionRegistry *registry, const string &msg = "", DWORD lastOsError = 0); 25 | inline string& getMessage() { return m_message; } 26 | private: 27 | string m_message; 28 | void init(IRuntimeExceptionRegistry *registry, const string &msg = "", DWORD lastOsError = 0); 29 | }; 30 | 31 | class IRuntimeExceptionRegistry{ 32 | public: 33 | /** Register exception */ 34 | virtual void registerException(RuntimeException &e) = 0; 35 | virtual string getLastException() = 0; 36 | virtual void clearLastExceptionMessage() = 0; 37 | }; 38 | 39 | class ExecutionContext: public IRuntimeExceptionRegistry 40 | { 41 | public: 42 | ExecutionContext() {} 43 | virtual ~ExecutionContext(); 44 | 45 | /** 46 | Converts ANSI string to Unicode. 47 | Allocates memory if needed. Memory is freed auto on scope exit. 48 | 49 | @param srcString source ANSI string with trailing zero char. 50 | @param strLen length of srcString in characters. 51 | @param buf preallocated buffer 52 | */ 53 | wchar_t* convertAtoW(const char *srcString, int strLen = -1, wchar_t *buf = NULL); 54 | 55 | /** 56 | Converts ANSI string length to Unicode string length. 57 | No memory is allocated. 58 | 59 | @param srcString source ANSI string with trailing zero char. 60 | @param strLen length of srcString in characters (not counting zero char). 61 | 62 | @return length of Unicode string in characters (not counting zero char) 63 | */ 64 | int strlenAtoW(const char *srcString, int strLen = -1); 65 | 66 | /** 67 | Converts Unicode string to ANSI. 68 | Allocates memory if needed. Memory is freed auto on scope exit. 69 | 70 | @param srcString source Unicode string with trailing zero char. 71 | @param strLen length of srcString in characters. 72 | @param buf preallocated buffer 73 | */ 74 | char* convertWtoA(const wchar_t *srcString, int strLen = -1, char *buf = NULL); 75 | 76 | /** 77 | Converts Unicode string length to ANSI string length. 78 | No memory is allocated. 79 | 80 | @param srcString source Unicode string with trailing zero char. 81 | @param strLen length of srcString in characters (not counting zero char). 82 | 83 | @return length of Unicode string in characters (not counting zero char) 84 | */ 85 | int strlenWtoA(const wchar_t *srcString, int strLen = -1); 86 | 87 | /** Register exception text */ 88 | void registerException(RuntimeException &e); 89 | 90 | 91 | virtual string getLastException(); 92 | 93 | virtual void clearLastExceptionMessage() { m_lastExceptionMessage = ""; } 94 | 95 | /** 96 | Allocates buffer for data, pointers to which are passed as params. 97 | Callers of setParam must copy data to the buffer in order to pass the pointer to it as param. 98 | This is needed for re-entrance. 99 | These buffers are freed automatically on ParamStorage scope's exit 100 | 101 | @param size Buffer size in bytes. 102 | 103 | @return Pointer to allocated buffer 104 | */ 105 | BYTE * allocateBuffer(int size, int align = 1); 106 | 107 | virtual void clear(); 108 | 109 | protected: 110 | /** Allocated param buffers */ 111 | vector m_buffers; 112 | 113 | /** Allocated param buffers sizes*/ 114 | vector m_bufferSizes; 115 | 116 | /** The last exception occured during calls to ExecutionContext. 117 | TODO store previous exceptions */ 118 | string m_lastExceptionMessage; 119 | 120 | void clearBuffers(); 121 | }; 122 | 123 | /** 124 | Class implementing storage of and access to params of a method . 125 | TODO merge to class Method 126 | 127 | */ 128 | class ParamStorage: public ExecutionContext { 129 | public: 130 | BYTE * getParamAddr(int paramIndex); 131 | /** 132 | Ctor. 133 | 134 | @param paramTypes Array of param Types (metadata) 135 | */ 136 | //ParamStorage(vector ¶mTypes, BYTE* argsPtr = NULL); 137 | ParamStorage(vector ¶ms, BYTE* argsPtr = NULL); 138 | ParamStorage() : m_storageType(Type()) {} 139 | 140 | /** 141 | Dtor. 142 | */ 143 | virtual ~ParamStorage(); 144 | 145 | 146 | /** 147 | Frees the allocated buffers and clears the params values. 148 | Must be called before re-using the ParamStorage instance. 149 | */ 150 | //void clearParamData(); 151 | 152 | virtual void clear(); 153 | 154 | size_t getArgStackSize(); 155 | inline void setArgsPtr(BYTE *argsPtr) { m_paramDataPtr = argsPtr; } 156 | 157 | void dumpData(const string &text = ""); 158 | protected: 159 | 160 | /** Packed params binary values ready to be passed to a C function */ 161 | blob m_paramDataBuf; 162 | BYTE* m_paramDataPtr; 163 | 164 | private: 165 | 166 | /** Init */ 167 | void init(); 168 | 169 | protected: 170 | /** Storage metadata */ 171 | Type m_storageType; 172 | 173 | 174 | /** Param offsets in m_paramData */ 175 | vector m_paramPointers; 176 | 177 | }; 178 | 179 | class Library: public ExecutionContext { 180 | public: 181 | Library(const string &libraryName, bool delayLoad = false); 182 | virtual ~Library(); 183 | DWORD getMethodAddr(const string &methodName, bool enableTCharSuffix = true); 184 | Type& getMethodType(const string &methodName); 185 | MethodInstance* createMethodInstance(const string& methodDecl, bool enableTCharSuffix); 186 | //MethodType* createMethodType(char * methodName, char *returnType, 187 | // char *paramTypes[], int paramCount, bool isStdCall = true, bool isUnicode = false); 188 | 189 | // IRuntimeExceptionRegistry 190 | /** Register exception */ 191 | 192 | private: 193 | void ensureIsLoaded(); 194 | string m_libraryName; 195 | HMODULE m_libraryHandle; 196 | string m_nameSpace; 197 | }; 198 | 199 | 200 | class Method: public ParamStorage 201 | { 202 | public: 203 | BYTE* getReturnValueAddr(); 204 | virtual void clear(); 205 | 206 | void invoke(MethodInstance *methodInstance); 207 | Method(MethodType *methodType, BYTE* argsPtr = NULL); 208 | virtual ~Method(); 209 | inline MethodType *getMethodType() { return m_methodType; } 210 | private: 211 | MethodType *m_methodType; 212 | vector m_returnValue; 213 | }; 214 | 215 | typedef boost::shared_ptr MethodContextPtr; --------------------------------------------------------------------------------