Patrice,
I added sin,cos,acos,asin,atan,atan2,sqrt,time,rand,srand,fmod,fmodf to TCLib.
If there are other ones you need for testing let me know.
I am going to add most all the math functions but I want to install the new Visual Studio 2017 community today.
James
James
That doesn't work by me, from inside the IDE, no DllMain external symbol.
and a bunch of unresolved external
Did you try to compile the DLL project that was in my zip?
Thanks anyway ;)
Patrice,
You have to be careful with your #includes and not #include files that in turn #include the standard <c lib headers>.
This appears to be the case with mfapi.h amd shlwapi.h
Probably just not worth the effort with the type of apps/dlls you write.
James
Patrice,
There are no issues with the GL.h and GLU.h.
Maybe if you prototyped just the calls from mfapi.h and shlwapi.h you use I could figure it out.
I am close I think ?? :)
James
i shall make another try later this day, after adding the missing DllMain entry point.
thanks
Patrice,
Try to make another standard Visual studio project like the one you posted without including mfapi.h and shlwapi.h, instead add the prototypes of the functions used in the source. I forgot to add tan (DUH) to TCLib so that will fail until I update and post a new TCLib.
Also there are a couple of calls in IsFileImage that are not supported (yet):
_wsplitpath_s
wcsncat_s
wcsstr
James
rand, and srand are causing me havoc
--> redefinition, previous definition was 'function'.
Patrice,
Yeah that is one of the issues you have to be aware of. One of your includes is also including the sdk <stdlib.h>
It's going to take a bit more planning on your part on managing #include files and prototypes.
What I would suggest if/when you decide to continue is to create tour own versions of includes you need and put them in the TCLib folder.
I have a mixed version (bc9/c++) of your dll compiled but don't quite know what to do with it to test?
It comes in at 12k.
James
I don't know how to resolve these 3 link errors (see the attached screen shot)
...
Patrice,
I updated the library and it should help.
Attached is the new library and includes along with my version of your dll.
To compile: TBLIBDLL.BAT LB01
James
I just noticed I hadn't finished up work in IsFileImage so it will not work as is.
James
I could remove the IsFileImage function, because in that specific case, a texture should be always a valid image file name.
I have written my own replacement for PathCombine, based on direct use of the RtlMoveMemory
void Path_Combine(OUT WCHAR* zResource, IN WCHAR* path, IN WCHAR* combine) {
long offset = (long) wcslen(path) * sizeof(WCHAR);
ZeroMemory(zResource, MAX_PATH);
MoveMemory(zResource, path, offset);
MoveMemory(&zResource[offset / 2], &combine[0], (long) wcslen(combine) * sizeof(WCHAR));
}
Patrice,
It's just the header files that are giving the problems.
Make your own for shlwapi.h in case you need something in the future and use #pragma comment(lib,"shlwapi.lib")
EXTERN_C LPWSTR PathCombineA(_Out_writes_(MAX_PATH) LPWSTR pszDest, _In_opt_ LPCTSTR pszDir, _In_opt_ LPCTSTR pszFile);
EXTERN_C LPWSTR PathCombineW(_Out_writes_(MAX_PATH) LPWSTR pszDest, _In_opt_ LPCWSTR pszDir, _In_opt_ LPCWSTR pszFile);
#ifdef UNICODE
#define PathCombine PathCombineW
#else
#define PathCombine PathCombineA
#endif
#define _MAX_DRIVE 3
#define _MAX_DIR 256
#define _MAX_FNAME 256
#define _MAX_EXT 256
James
James--
From 108 Kb down to 13 Kb, that's amazing!!!
However in Math.h, i still couldn't use
extern int (__cdecl* rand)(void);
extern void (__cdecl* srand)(unsigned int);
because of error C2365: previous definition was function
Does this help...
#ifdef TCLib
int rand(void)
{
static unsigned int next = 1;
next = next * 1103515245 + 12345;
return (unsigned int)(next>>16) & RAND_MAX;
}
#endif
size_t Rnd(int iMin, int iMax)
{
double dblRange=iMax-iMin;
double dblMaxFactor=dblRange/RAND_MAX;
double dblRandomNumber=(double)rand();
return iMin+dblMaxFactor*dblRandomNumber;
}
I was working with that some time ago. I forget the details, and I forget where RAND_MAX is defined. Possibly in stdlib.h. My Rnd() function above is a quick and dirty interpretation of PowerBASIC's Rnd(), where one can specify a min and max value. It just scales stuff about using stdlib's rand. It worked OK for the use I made of it. Random number generation can get to be a tricky subject if you let it!
Patrice,
You must have an include file somewhere including <stdlib.h> .
I'll try renaming them to see if that helps.
James
Patrice,
This is the test code I used for the math functions.
James
// *********************************************************************
// Created with bc9Basic - BASIC To C/C++ Translator (V) 9.2.6.0 (2017/02/05)
// The bc9Basic translator (bc9.exe) was compiled with
// g++ (tdm64-1) 5.1.0
// ----------------------------------------------------------------------
// BCX (c) 1999 - 2009 by Kevin Diggins
// *********************************************************************
// Translated for compiling with the
// Microsoft (R) C/C++ Optimizing Compiler
// On MS Windows
// Using TCLib by Fred Harris
// *********************************************************************
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#define _X(y) y
#include <windows.h>
#define x64
#include "TCLib\stdio.h"
#include "TCLib\string.h"
#include "TCLib\stdlib.h"
#include "TCLib\memory.h"
#include "TCLib\malloc.h"
#include "TCLib\math.h"
#include "TCLib\tchar.h"
#include "TCLib\Strings.cpp"
typedef String fstring;
FILE* stdin;
FILE* stdout;
FILE* stderr;
//<---UNICODE AWARE
#define SFMT (const char*)"%s\r\n"
//>---UNICODE AWARE
// NO HEADERS START
#ifndef _WINDOWS_
//<---UNICODE AWARE
typedef _TCHAR *PCHAR, *LPCH, *PCH, *NPSTR, *LPSTR, *PSTR;
typedef unsigned long DWORD, *PDWORD, *LPDWORD;
typedef unsigned int UINT;
//>---UNICODE AWARE
#endif
// NO HEADERS END
// ***************************************************
// Compiler Defines
// ***************************************************
// C++
#if defined( __cplusplus )
#define overloaded
#define C_EXPORT EXTERN_C __declspec(dllexport)
#define C_IMPORT EXTERN_C __declspec(dllimport)
#define BEGIN_EXTERN_C extern _T("C") {
#define END_EXTERN_C }
#else
#define C_EXPORT __declspec(dllexport)
#define C_IMPORT __declspec(dllimport)
#endif
// Microsoft VC++
#ifndef DECLSPEC_UUID
#if (_MSC_VER >= 1100) && defined ( __cplusplus )
#define DECLSPEC_UUID(x) __declspec(uuid(x))
#else
#define DECLSPEC_UUID(x)
#endif
#endif
// ***************************************************
// Compiler Defines
// ***************************************************
#ifndef __cplusplus
#error A C++ compiler is required
#endif
// *************************************************
// User's GLOBAL ENUM blocks
// *************************************************
// *************************************************
// System Defined Constants
// *************************************************
typedef const _TCHAR* ccptr;
#define CCPTR const _TCHAR*
#define cfree free
//<---UNICODE AWARE
typedef char _char;
#define _strlen strlen
//>---UNICODE AWARE
#define EQU ==
#define NOT_USED(x) if(x);
#define CTLHNDL(id) GetDlgItem(hWnd,id)
#define cSizeOfDefaultString 2048
// *************************************************
// User Defined Constants
// *************************************************
#define PI 3.141592653589753
#define TR 57.2957795130831
// *************************************************
// Standard Prototypes
// *************************************************
_TCHAR* BCX_TmpStr(size_t, size_t = 0, int = 1);
void Pause (void);
// *************************************************
// System Variables
// *************************************************
#define LDOUBLE long double
// *************************************************
// User Defined Types, Unions and Classes
// *************************************************
// *************************************************
// User Global Variables
// *************************************************
// *************************************************
// User Prototypes
// *************************************************
int _tmain (void);
// *************************************************
// User Global Initialized Arrays
// *************************************************
// *************************************************
// Runtime Functions
// *************************************************
#ifndef BCXTmpStrSize
#define BCXTmpStrSize 2048
#endif
_TCHAR *BCX_TmpStr (size_t Bites, size_t iPad, int iAlloc)
{
static int StrCnt;
static _TCHAR *StrFunc[BCXTmpStrSize];
StrCnt = (StrCnt + 1) & (BCXTmpStrSize - 1);
if(StrFunc[StrCnt]) {
free (StrFunc[StrCnt]);
StrFunc[StrCnt] = NULL;
}
#if defined BCX_MAX_VAR_SIZE
if(Bites * sizeof(_TCHAR) > BCX_MAX_VAR_SIZE)
{
_tprintf(_T("Buffer Overflow caught in BCX_TmpStr - requested space of %d EXCEEDS %d\n"), (int)(Bites * sizeof(_TCHAR)), BCX_MAX_VAR_SIZE);
abort();
}
#endif
if(iAlloc) StrFunc[StrCnt] = (_TCHAR*)calloc(Bites + iPad + 1, sizeof(_TCHAR));
return StrFunc[StrCnt];
}
void Pause(void)
{
_tprintf(_T("\n%ls\n"), _T("Press any key to continue..."));
_getwch();
}
// *************************************************
// User Subs, Functions and Class Methods
// *************************************************
int _tmain ()
{
LDOUBLE ld = {0};
double d1 = {0};
float f1 = {0};
int I = {0};
ld = sin( 45 / TR);
_tprintf(_T("%.19LG\n"), (LDOUBLE)ld);
I = sin( 45 / TR);
d1 = sin( 45 / TR);
f1 = sin( 45 / TR);
_tprintf(_T("%d\n"), (int)I);
_tprintf(_T("%.15G\n"), (double)d1);
_tprintf(_T("%.7G\n"), (float)f1);
ld = cos( 45 / TR);
_tprintf(_T("%.19LG\n"), (LDOUBLE)ld);
ld = acos( 45 / TR);
d1 = sqrt( 144);
_tprintf(_T("%.15G\n"), (double)d1);
I = time( NULL);
_tprintf(_T("%ls%d\n"), _T("I = "), (int)I);
_tprintf(_T("%ls\n"), _T("Hello There"));
I = rand();
_tprintf(_T("%ls%d\n"), _T("I = "), (int)I);
srand((DWORD)time(NULL));
d1 = fmod( 5.3, 2);
_tprintf(_T("%ls%.15G\n"), _T("d1 = "), (double)d1);
f1 = fmodf( 5.3, 2);
_tprintf(_T("%ls%.7G\n"), _T("f1 = "), (float)f1);
Pause();
}
#define RAND_MAX 0x7fff belongs to stdlib.h so it should be defined explicitly elsewhere since stdlib.h is eliminated altogether.
James
The main difference between you and me is that you don't use the IDE.
I have attached the full VS 2015 community project to create the 64-bit OpenGL bbp_Laserbeam.dll (13312 bytes) to be used with the latest MBox64.exe player.
I shall try to convert the other plugins, once the rand() and srand() problem will be sorted out ;)
Thank you for helping me to produce this tiny visual plugin.
As a matter of comparison the size of the PowerBASIC 32-bit LaserBeam.dll plugin is 35328 bytes, that means 2.65 bigger, i am very happy!
Patrice,
Try this one.
James
Fred
Thanks for the rand and rnd functions, i didn't see your post until today.
Fred
What do you use to replace the srand function to seed the pseudorandom-number ?
Amazing
i have been able to reduce the size of most of my plugins by a factor ranging between 4 and 7 !!!
Patrice, I don't think I have any implementation for srand(). I had only run into the problem of coming up with a replacement for PowerBASIC's Rnd() function in converting a multi-threaded example I posted here some time ago...
http://www.jose.it-berater.org/smfforum/index.php?topic=5058.0
...from PowerBASIC to C++. As you are probably aware, C's rand produces a rather limited range of integers. I forget the exact range, but its rather limited. For my example I needed numbers like PowerBASIC's Rnd() would generate, so I scaled them into an acceptable range.
Later, when I attempted to get that example working with my TCLib, I ran into the same problem you did, that is, I hadn't included in TCLib an implementation of rand() or srand(). So I hunted around on the internet a bit and found what I did for rand() and that by itself met my simple needs at the time. The implementation seems to use integer overflow to get crazy numbers.
Just off the top of my head, I think there are two solutions possible if you need rand() or srand(). First, you could hunt around the internet for an implementation of srand(). My guess is it wouldn't be too hard to come up with something.
The other possibility would be to simply include it within TCLib itself in the manner Jim seems to have done with the trig and other Math functions. Its a fairly straightforward process. As I've said before, the C Runtime is loaded into every GUI process. All the C Runtime functions are there, including, I'm assuming, rand() and srand(). Its just a matter of calling LoadLibrary() to get the dll HINSTANCE, and calling GetProcAddress() to get a pointer to the function. In many cases the function pointer can be named exactly the same as the function itself, and the usage is the same.
Patrice,
I noticed in your bbp_Laserbeam.cpp source you are not including TCLib\tchar.h.
This is a vital component that eliminates the duplicate definitions for rand srand.
James
LoadLibrary() to get the dll HINSTANCE, and calling GetProcAddress()
OF COURSE, that could be the easiest solution!
Fred,
I have found that renaming the functions in the TCLib and then using tchar.h for the translation seems to work fine.
For rand and srand I just prefaced with an underscore but I am going to go back and preface everything with tcl_.
I found I needed fflush so :
tcl_fflush = (int (__cdecl*)(FILE* fp)) GetProcAddress(hLib,"fflush");
Then in tchar.h:
#define fflush tcl_fflush
James
Quote from: Frederick J. Harris on March 10, 2017, 06:08:40 PM... C's rand produces a rather limited range of integers. I forget the exact range, but its rather limited.
The ISO standard declares a compatible C rand() function's exact range to be entirely compiler implementation dependent but states that it be at least 0 thru 32767 inclusive. As it happens, both VC and GCC define their
RAND_MAX value as
0x7FFF, which is exactly 32767 decimal.
Here is what i came with to simulate the PowerBASIC:
RANDOMIZE TIMER
typedef void (*FuncWithParams)(DWORD seed);
void RandoMize(IN DWORD seed) {
HMODULE hModule = LoadLibrary(L"MSVCRT");
if (hModule) {
FuncWithParams hProc;
hProc = (FuncWithParams) GetProcAddress(hModule, "srand");
if (hProc) { hProc(seed); }
}
}
void RandomizeTimer() {
// //static long done;
// //if (!done) { srand((DWORD) time(NULL)); done = !done; }
//srand((DWORD) time(NULL));
RandoMize((DWORD) time(NULL));
}
i shall post the source code of all the new TCLib plugins on www.objreader.com to render in Mbox64.exe
...
i was missing the log2 function.
here is what i came with
#define M_LOG2E 1.44269504088896340736
#define double_proc typedef double (__stdcall *zProc)
HMODULE MSVCRT() {
static HMODULE hModule;
if (hModule == 0) { hModule = LoadLibrary(L"MSVCRT"); }
return hModule;
}
double log2(IN double X) {
double l2 = 0;
HMODULE hModule = MSVCRT();
if (hModule) {
double_proc (double);
zProc hProc = (zProc) GetProcAddress(hModule, "log");
if (hProc) { l2 = hProc(X) * M_LOG2E; }
}
return l2;
}
Quote
The ISO standard declares a compatible C rand() function's exact range to be entirely compiler implementation dependent but states that it be at least 0 thru 32767 inclusive. As it happens, both VC and GCC define their RAND_MAX value as 0x7FFF, which is exactly 32767 decimal.
That's the number I thought RAND_MAX was equal to for VC and GCC Mike, but I didn't want to state it without checking. At the time I needed it (rand()), I needed numbers from about a million to 50,000,000, so I had to devise something to produce them. I'm not really sure what's in the C++ Standard Library (if anything), relating to a C++ version of rand().
This is a satisfactory, though home-made 32-bit pseudo-randomizer. It churns integers but scales them to return floats -1.0 to +1.0. To return 32bit integer ranges, omit the float scaler and return the raw integer value in eax instead.
int seed=0x12345678
'
function Rnd() as float
=======================
Static As float f, d=1/0x7fffffff
mov eax,seed
inc eax
rol eax,13
xor eax,0xdab5ca3a
mov seed,eax
push eax
fild dword [esp]
pop eax
fmul dword d
fstp dword f
return f
end function
You are probably familiar with this one from the web, based on mul overflows into edx.
The 2 inputs are the lower and upper range limits:
function irnd(int z1, z2) as int
================================
mov eax,z2
sub eax,z1
inc eax
imul edx,Seed,0x8088405
inc edx
mov Seed,edx 'store new seed
mul edx 'multiply eax by edx
return edx+z1
end Function
The TCLib version of the Visual Studio community 2015 has been attached to this post
http://www.jose.it-berater.org/smfforum/index.php?topic=5176.msg22444#msg22444
Thank you all, for having helped me to produce these amazing small 64-bit DLL(s), without using any compressor !
So far i have been able to create my smallest OpenGL 64-bit plugin, only 13 Kb.
And i was able to reduce the size of my PNGanim project from 140 Kb down to 60 Kb, using GetprocAdress to access directly to MSVCRT, the only thing that is causing me havoc, is when there are multiple optional parameters like for swprintf, and i don't know the syntax to use to create the prototype to use the "...".
Patrice,
Take a look at the TCLib\stdio.h file.
James
James--
I have seen it already, but what i am looking for is a replacement for the PowerBASIC statement "AS ANY"
without using va_list
Currently i am doing this to use swprintf with long, and i must have another function for float, double, etc.
#define long_proc_c typedef long (__cdecl *zProc)
HMODULE MSVCRT() {
static HMODULE hModule;
if (hModule == 0) { hModule = LoadLibrary(L"MSVCRT"); }
return hModule;
}
long long_swprintf(OUT WCHAR* buffer, IN WCHAR* format, IN long N) {
long nRet = -1; // Error
HMODULE hModule = MSVCRT();
if (hModule) {
long_proc_c (WCHAR*, WCHAR*, long);
zProc hProc = (zProc)GetProcAddress(hModule, "swprintf");
if (hProc) { nRet = hProc(buffer, format, N); }
}
return nRet;
}
James, Fred,
I have attached the latest Visual Studio 2015/2017 TCLIB version of my 64-bit OpenGL plugins
to this post (http://www.objreader.com/index.php?topic=80.0)
C++bbp_plugins64.zip
The smallest dll is only 13 Kb.
Thanks Patrice,
I realize now why you were having problems with rand and srand as I found issues with my own work.
I assume one of your included files:
#include <gl/GL.h>
#include <gl/GLU.h>
is pulling in <stdlib.h> or one of the other msvcrt include files.
I had done a lot of successful testing originally with my port of José's CWindow and Afx framework but when I tried with my latest version of TCLib I had a number of redefinition errors.
I was including:
#include <psapi.h>
#include <Shlobj.h>
#include <KnownFolders.h>
#include <shlwapi.h>
#include <commctrl.h>
#include <uxtheme.h>
and at least one of them is pulling in msvcrt include files.
I write all my bc9Basic code as ansi. I then parse the c++ translated code with the ULEX utility which does all the transformations. I can name the library function tcl_rand and translate the source "rand" call to tcl_rand on the fly.
I am scratching my head though as only a few are a causing problems.
James