Board ArchivesSite FeaturesActiveworlds SupportHistoric Archives |
tony mcgrath // User Search
tony mcgrath // User SearchGetting Started with SDKJan 27, 1999, 2:19pm
The real problem here is the fact that the Borland compilers prepend a "_"
to external identifiers and the aw.dll exports its entry points without a prepended "_", which means that the Borland linker cannot find the function references. The redefinition of these entry points using the DEF file is one solution that will probably work with most Borland compilers. There is another solution which avoids the whole naming problem which uses the Windows API LoadLibrary/GetProcAddress mechanism to load the addresses directly out of the AW.DLL file at run-time. This does work (I have used it in a C++Builder 3 component that implements the current SDK) and does not rely on having to update the DEF files if the SDK changes. Here is a copy of some C code that will do the job. It requires that you redefine the SDK header file to replace the API functions with the following definitions. /* Modified aw.h for use with LoadLibrary/GetProcAddress */ #define AW_MAX_ATTRIBUTE_LENGTH 255 #define AW_BUILD 12 #ifdef __cplusplus extern "C" { #endif /*-------------------------------------------------------------------------- --- a t t r i b u t e s ---------------------------------------------------------------------------- -*/ typedef enum { AW_LOGIN_NAME, AW_LOGIN_PASSWORD, AW_LOGIN_OWNER, AW_LOGIN_PRIVILEGE_PASSWORD, AW_LOGIN_PRIVILEGE_NUMBER, AW_LOGIN_PRIVILEGE_NAME, AW_LOGIN_PRIVACY, AW_LOGIN_APPLICATION, AW_LOGIN_EMAIL, /* not used by the SDK */ AW_UNIVERSE_BROWSER_MINIMUM, AW_UNIVERSE_BROWSER_RELEASE, AW_UNIVERSE_BROWSER_BETA, AW_UNIVERSE_WORLD_MINIMUM, AW_UNIVERSE_WORLD_START, AW_UNIVERSE_REGISTRATION_REQUIRED, AW_UNIVERSE_BUILD_NUMBER, AW_UNIVERSE_REGISTRATION_CHARGE, AW_UNIVERSE_RENEWAL_CHARGE, AW_CITIZEN_NUMBER, AW_CITIZEN_NAME, AW_CITIZEN_PASSWORD, AW_CITIZEN_EMAIL, AW_CITIZEN_TIME_LEFT, AW_CITIZEN_PRIVILEGE_PASSWORD, AW_CITIZEN_IMMIGRATION_TIME, AW_CITIZEN_EXPIRATION_TIME, AW_CITIZEN_BETA, AW_CITIZEN_LAST_LOGIN, AW_CITIZEN_BOT_LIMIT, AW_WORLD_NAME, AW_WORLD_TITLE, AW_WORLD_BACKDROP, AW_WORLD_GROUND, AW_WORLD_OBJECT_PATH, AW_WORLD_OBJECT_REFRESH, AW_WORLD_BUILD_RIGHT, AW_WORLD_EMINENT_DOMAIN_RIGHT, AW_WORLD_ENTER_RIGHT, AW_WORLD_SPECIAL_OBJECTS_RIGHT, AW_WORLD_BACKDROP_RED, AW_WORLD_BACKDROP_GREEN, AW_WORLD_BACKDROP_BLUE, AW_WORLD_CARETAKER_CAPABILITY, AW_WORLD_RESTRICTED_RADIUS, AW_WORLD_PUBLIC_SPEAKER_CAPABILITY, AW_WORLD_PUBLIC_SPEAKER_RIGHT, AW_WORLD_CREATION_TIMESTAMP, AW_WORLD_HOME_PAGE, AW_WORLD_BUILD_NUMBER, AW_WORLD_OBJECT_PASSWORD, AW_WORLD_DISABLE_CREATE_URL, AW_WORLD_RATING, AW_WORLD_WELCOME_MESSAGE, AW_WORLD_EJECT_RIGHT, AW_WORLD_EJECT_CAPABILITY, AW_WORLD_CELL_LIMIT, AW_WORLD_BUILD_CAPABILITY, AW_WORLD_ALLOW_PASSTHRU, AW_WORLD_ALLOW_FLYING, AW_WORLD_ALLOW_TELEPORT, AW_WORLD_AVATARS_IN_SCENE, AW_WORLD_ALLOW_OBJECT_SELECT, AW_WORLD_BOTS_RIGHT, AW_WORLD_SPEAK_CAPABILITY, AW_WORLD_SPEAK_RIGHT, AW_MY_X, AW_MY_Y, AW_MY_Z, AW_MY_YAW, AW_MY_TYPE, AW_MY_GESTURE, AW_AVATAR_SESSION, AW_AVATAR_NAME, AW_AVATAR_X, AW_AVATAR_Y, AW_AVATAR_Z, AW_AVATAR_YAW, AW_AVATAR_TYPE, AW_AVATAR_GESTURE, AW_CHAT_SESSION, AW_CHAT_MESSAGE, AW_CELL_X, AW_CELL_Z, AW_CELL_SEQUENCE, AW_CELL_SIZE, AW_OBJECT_NUMBER, AW_OBJECT_X, AW_OBJECT_Y, AW_OBJECT_Z, AW_OBJECT_YAW, AW_OBJECT_MODEL, AW_OBJECT_DESCRIPTION, AW_OBJECT_ACTION, AW_OBJECT_OLD_NUMBER, AW_OBJECT_OLD_X, AW_OBJECT_OLD_Z, AW_OBJECT_OWNER, AW_OBJECT_SESSION, AW_OBJECT_BUILD_TIMESTAMP, AW_QUERY_COMPLETE, AW_CHAT_TYPE, AW_LICENSE_NAME, AW_LICENSE_PASSWORD, AW_LICENSE_USERS, AW_LICENSE_RANGE, AW_LICENSE_EMAIL, AW_LICENSE_COMMENT, AW_LICENSE_CREATION_TIME, AW_LICENSE_EXPIRATION_TIME, AW_LICENSE_LAST_START, AW_WORLDLIST_NAME, AW_WORLDLIST_STATUS, AW_WORLDLIST_USERS, AW_EJECT_SESSION, AW_EJECT_DURATION, AW_EJECTION_ADDRESS, AW_EJECTION_EXPIRATION, AW_DISCONNECT_REASON, AW_FILE_NAME, AW_FILE_RECIPIENT, AW_FILE_SENDER, AW_FILE_SENDER_NAME, AW_FILE_SESSION, AW_FILE_ADDRESS, AW_FILE_PORT, /* attributes below are not used by the SDK */ AW_CONTACT_NUMBER, AW_CONTACT_STATUS, AW_CONTACT_NAME, AW_CONTACT_WORLD, AW_CONTACT_MORE, AW_TELEGRAM_TO, AW_TELEGRAM_FROM, AW_TELEGRAM_TEXT, AW_TELEGRAM_SENT, AW_TELEGRAM_MORE, AW_JOIN_NAME, AW_JOIN_CITIZEN, AW_JOIN_WORLD, AW_JOIN_X, AW_JOIN_Y, AW_JOIN_Z, AW_JOIN_YAW, AW_REGISTER_CC_NAME, AW_REGISTER_CC_NUMBER, AW_REGISTER_CC_MONTH, AW_REGISTER_CC_YEAR, AW_REGISTER_ADDRESS, AW_REGISTER_CITY, AW_REGISTER_STATE, AW_REGISTER_ZIP, AW_REGISTER_PHONE_NUMBER, AW_REGISTER_BUSINESS_NAME, AW_REGISTER_VENDOR, AW_REGISTER_RESULT, AW_MAX_ATTRIBUTE } AW_ATTRIBUTE; typedef enum { AW_EVENT_AVATAR_ADD, AW_EVENT_AVATAR_CHANGE, AW_EVENT_AVATAR_DELETE, AW_EVENT_CELL_BEGIN, AW_EVENT_CELL_OBJECT, AW_EVENT_CELL_END, AW_EVENT_CHAT, AW_EVENT_OBJECT_ADD, AW_EVENT_OBJECT_DELETE, AW_EVENT_UNIVERSE_ATTRIBUTES, AW_EVENT_WORLD_ATTRIBUTES, AW_EVENT_WORLD_INFO, AW_EVENT_WORLD_DISCONNECT, AW_EVENT_SEND_FILE, AW_EVENT_CONTACT_STATE, AW_EVENT_TELEGRAM, AW_EVENT_JOIN, AW_MAX_EVENT } AW_EVENT_ATTRIBUTE; typedef enum { AW_CALLBACK_LOGIN, AW_CALLBACK_ENTER, AW_CALLBACK_OBJECT_RESULT, AW_CALLBACK_LICENSE_ATTRIBUTES, AW_CALLBACK_LICENSE_RESULT, AW_CALLBACK_CITIZEN_ATTRIBUTES, AW_CALLBACK_CITIZEN_RESULT, AW_CALLBACK_QUERY, AW_CALLBACK_WORLD_LIST, AW_CALLBACK_SEND_FILE, AW_CALLBACK_JOIN, AW_CALLBACK_PASSWORD_SEND, AW_CALLBACK_IMMIGRATE, AW_CALLBACK_REGISTER, AW_MAX_CALLBACK } AW_CALLBACK; typedef enum { AW_CHAT_SAID, AW_CHAT_BROADCAST, AW_CHAT_WHISPER, } AW_CHAT_TYPES; typedef enum { AW_CONTACT_OFFLINE, AW_CONTACT_ONLINE, AW_CONTACT_NOT_A_CITIZEN } AW_CONTACT_STATES; typedef enum { AW_WORLDSTATUS_UNKNOWN, AW_WORLDSTATUS_PUBLIC, AW_WORLDSTATUS_PRIVATE } AW_WORLD_STATES; extern int __cdecl (*aw_init) (int build); extern void __cdecl (*aw_term) (void); extern int __cdecl (*aw_create) (const char* domain, int port, void** instance); extern int __cdecl (*aw_create_resolved) (unsigned long address, int port, void** instance); extern int __cdecl (*aw_destroy) (void); extern void* __cdecl (*aw_instance) (void); extern int __cdecl (*aw_instance_set) (void *instance); extern int __cdecl (*aw_login) (void); extern int __cdecl (*aw_wait) (int milliseconds); extern int __cdecl (*aw_int) (AW_ATTRIBUTE a); extern int __cdecl (*aw_int_set) (AW_ATTRIBUTE a, int value); extern char* __cdecl (*aw_string) (AW_ATTRIBUTE a); extern int __cdecl (*aw_string_set) (AW_ATTRIBUTE a, const char *value); extern int __cdecl (*aw_bool) (AW_ATTRIBUTE a); extern int __cdecl (*aw_bool_set) (AW_ATTRIBUTE a, int value); extern void __cdecl (*(*aw_callback) (AW_CALLBACK c)) (int rc); extern int __cdecl (*aw_callback_set) (AW_CALLBACK c, void (*callback) (int rc)); extern void __cdecl (*(*aw_event) (AW_EVENT_ATTRIBUTE a))(void); extern int __cdecl (*aw_event_set) (AW_EVENT_ATTRIBUTE a, void (*handler) (void)); extern int __cdecl (*aw_enter) (const char* world, int avatars); extern int __cdecl (*aw_exit) (void); extern int __cdecl (*aw_say) (const char* message); extern int __cdecl (*aw_whisper) (int session_id, const char* message); extern int __cdecl (*aw_state_change) (void); extern int __cdecl (*aw_citizen_attributes_by_name) (const char* name); extern int __cdecl (*aw_citizen_attributes_by_number) (int citizen); extern int __cdecl (*aw_citizen_add) (void); extern int __cdecl (*aw_citizen_change) (void); extern int __cdecl (*aw_citizen_delete) (int citizen); extern int __cdecl (*aw_citizen_next) (void); extern int __cdecl (*aw_citizen_previous) (void); extern int __cdecl (*aw_license_add) (void); extern int __cdecl (*aw_license_attributes) (const char* name); extern int __cdecl (*aw_license_change) (void); extern int __cdecl (*aw_license_delete) (const char* name); extern int __cdecl (*aw_license_next) (void); extern int __cdecl (*aw_license_previous) (void); extern int __cdecl (*aw_world_list) (void); extern int __cdecl (*aw_object_add) (void); extern int __cdecl (*aw_object_change) (void); extern int __cdecl (*aw_object_delete) (void); extern int __cdecl (*aw_query) (int x_sector, int z_sector, int sequence[3][3]); extern int __cdecl (*aw_random) (void); extern int __cdecl (*aw_world_attributes_change) (void); extern int __cdecl (*aw_universe_attributes_change) (void); extern int __cdecl (*aw_session) (void); extern int __cdecl (*aw_world_eject) (void); extern int __cdecl (*aw_universe_ejection_add) (void); extern int __cdecl (*aw_sector_from_cell) (int cell); #ifdef __cplusplus } #endif Then you will need to add some code to load the addresses from the AW.DLL at run-time. The following code will do this. #ifdef __cplusplus extern "C" { #endif int __cdecl (*aw_init) (int build); void __cdecl (*aw_term) (void); int __cdecl (*aw_create) (const char* domain, int port, void** instance); int __cdecl (*aw_create_resolved) (unsigned long address, int port, void** instance); int __cdecl (*aw_destroy) (void); void* __cdecl (*aw_instance) (void); int __cdecl (*aw_instance_set) (void *instance); int __cdecl (*aw_login) (void); int __cdecl (*aw_wait) (int milliseconds); int __cdecl (*aw_int) (AW_ATTRIBUTE a); int __cdecl (*aw_int_set) (AW_ATTRIBUTE a, int value); char* __cdecl (*aw_string) (AW_ATTRIBUTE a); int __cdecl (*aw_string_set) (AW_ATTRIBUTE a, const char *value); int __cdecl (*aw_bool) (AW_ATTRIBUTE a); int __cdecl (*aw_bool_set) (AW_ATTRIBUTE a, int value); void __cdecl (*(*aw_callback) (AW_CALLBACK c))(int rc); int __cdecl (*aw_callback_set) (AW_CALLBACK c, void (*callback) (int rc)); void __cdecl (*(*aw_event) (AW_EVENT_ATTRIBUTE a))(void); int __cdecl (*aw_event_set) (AW_EVENT_ATTRIBUTE a, void (*handler) (void)); int __cdecl (*aw_enter) (const char* world, int avatars); int __cdecl (*aw_exit) (void); int __cdecl (*aw_say) (const char* message); int __cdecl (*aw_whisper) (int session_id, const char* message); int __cdecl (*aw_state_change) (void); int __cdecl (*aw_citizen_attributes_by_name) (const char* name); int __cdecl (*aw_citizen_attributes_by_number) (int citizen); int __cdecl (*aw_citizen_add) (void); int __cdecl (*aw_citizen_change) (void); int __cdecl (*aw_citizen_delete) (int citizen); int __cdecl (*aw_citizen_next) (void); int __cdecl (*aw_citizen_previous) (void); int __cdecl (*aw_license_add) (void); int __cdecl (*aw_license_attributes) (const char* name); int __cdecl (*aw_license_change) (void); int __cdecl (*aw_license_delete) (const char* name); int __cdecl (*aw_license_next) (void); int __cdecl (*aw_license_previous) (void); int __cdecl (*aw_world_list) (void); int __cdecl (*aw_object_add) (void); int __cdecl (*aw_object_change) (void); int __cdecl (*aw_object_delete) (void); int __cdecl (*aw_query) (int x_sector, int z_sector, int sequence[3][3]); int __cdecl (*aw_random) (void); int __cdecl (*aw_world_attributes_change) (void); int __cdecl (*aw_universe_attributes_change) (void); int __cdecl (*aw_session) (void); int __cdecl (*aw_world_eject) (void); int __cdecl (*aw_universe_ejection_add) (void); int __cdecl (*aw_sector_from_cell) (int cell); #ifdef __cplusplus } #endif void LoadAwDll(void) { HINSTANCE h; h = LoadLibrary("AW.DLL"); aw_init = (int(*)(int)) GetProcAddress(h, "aw_init"); aw_term = (void(*)(void)) GetProcAddress(h, "aw_term"); aw_create = (int(*)(const char*, int, void**)) GetProcAddress(h, "aw_create"); aw_create_resolved = (int(*)(unsigned long, int, void**)) GetProcAddress(h, "aw_create_resolved"); aw_destroy = (int(*)(void)) GetProcAddress(h, "aw_destroy"); aw_instance = (void*(*)(void)) GetProcAddress(h, "aw_instance"); aw_instance_set = (int(*)(void*)) GetProcAddress(h, "aw_instance_set"); aw_login = (int(*)(void)) GetProcAddress(h, "aw_login"); aw_wait = (int(*)(int)) GetProcAddress(h, "aw_wait"); aw_int = (int(*)(AW_ATTRIBUTE)) GetProcAddress(h, "aw_int"); aw_int_set = (int(*)(AW_ATTRIBUTE, int)) GetProcAddress(h, "aw_int_set"); aw_string = (char*(*)(AW_ATTRIBUTE)) GetProcAddress(h, "aw_string"); aw_string_set = (int(*)(AW_ATTRIBUTE, const char*)) GetProcAddress(h, "aw_string_set"); aw_bool = (int(*)(AW_ATTRIBUTE)) GetProcAddress(h, "aw_bool"); aw_bool_set = (int(*)(AW_ATTRIBUTE, int)) GetProcAddress(h, "aw_bool_set"); aw_callback = (void(*(*)(AW_CALLBACK))(int)) GetProcAddress(h, "aw_callback"); aw_callback_set = (int(*)(AW_CALLBACK, void(*)(int))) GetProcAddress(h, "aw_callback_set"); aw_event = (void(*(*)(AW_EVENT_ATTRIBUTE))(void)) GetProcAddress(h, "aw_event"); aw_event_set = (int(*)(AW_EVENT_ATTRIBUTE, void(*)(void))) GetProcAddress(h, "aw_event_set"); aw_enter = (int(*)(const char*, int)) GetProcAddress(h, "aw_enter"); aw_exit = (int(*)(void)) GetProcAddress(h, "aw_exit"); aw_say = (int(*)(const char*)) GetProcAddress(h, "aw_say"); aw_whisper = (int(*)(int, const char*)) GetProcAddress(h, "aw_whisper"); aw_state_change = (int(*)(void)) GetProcAddress(h, "aw_state_change"); aw_citizen_attributes_by_name = (int(*)(const char*)) GetProcAddress(h, "aw_citizen_attributes_by_name"); aw_citizen_attributes_by_number = (int(*)(int)) GetProcAddress(h, "aw_citizen_attributes_by_number"); aw_citizen_add = (int(*)(void)) GetProcAddress(h, "aw_citizen_add"); aw_citizen_change = (int(*)(void)) GetProcAddress(h, "aw_citizen_change"); aw_citizen_delete = (int(*)(int)) GetProcAddress(h, "aw_citizen_delete"); aw_citizen_next = (int(*)(void)) GetProcAddress(h, "aw_citizen_next"); aw_citizen_previous = (int(*)(void)) GetProcAddress(h, "aw_citizen_previous"); aw_license_add = (int(*)(void)) GetProcAddress(h, "aw_license_add"); aw_license_attributes = (int(*)(const char*)) GetProcAddress(h, "aw_license_attributes"); aw_license_change = (int(*)(void)) GetProcAddress(h, "aw_license_change"); aw_license_delete = (int(*)(const char*)) GetProcAddress(h, "aw_license_delete"); aw_license_previous = (int(*)(void)) GetProcAddress(h, "aw_license_previous"); aw_license_next = (int(*)(void)) GetProcAddress(h, "aw_license_next"); aw_world_list = (int(*)(void)) GetProcAddress(h, "aw_world_list"); aw_object_add = (int(*)(void)) GetProcAddress(h, "aw_object_add"); aw_object_change = (int(*)(void)) GetProcAddress(h, "aw_object_change"); aw_object_delete = (int(*)(void)) GetProcAddress(h, "aw_object_delete"); aw_query = (int(*)(int, int, int(*)[3])) GetProcAddress(h, "aw_query"); aw_random = (int(*)(void)) GetProcAddress(h, "aw_random"); aw_world_attributes_change = (int(*)(void)) GetProcAddress(h, "aw_world_attributes_change"); aw_universe_attributes_change = (int(*)(void)) GetProcAddress(h, "aw_universe_attributes_change"); aw_session = (int(*)(void)) GetProcAddress(h, "aw_session"); aw_world_eject = (int(*)(void)) GetProcAddress(h, "aw_world_eject"); aw_universe_ejection_add = (int(*)(void)) GetProcAddress(h, "aw_universe_ejection_add"); aw_sector_from_cell = (int(*)(int)) GetProcAddress(h, "aw_sector_from_cell"); } Of course, this code doesn't have any error checking added. I leave that as an exercise. I hope this helps those who are in need ;-) ToeKnee. [View Quote] This is getting a bit tenuous now... I'm compiling as a win32 console application, which according to borland accepts EXPORTS definitions so that should be hunky dorey..... And I've tried all of the logical permutations of _aw_init=aw_init, capitals, arrangement etc. Perhaps someone could mail me a complete awBC++.lib file (just to make sure it's not me being dumb emough to have miss-compiled the def file in some way). Failing that the only thing I can think of is using the __export command explicity in every line of the bot.c that calls an external function. D'ya reckon that's worth a shot? [View Quote] Well, sadly enough, Impdef causes the same Access Violation error message. Perhaps my programs are just too old to handle the newest form of VC++ DLL. (I am using Borland C++ 4.52) Most likely the problem. Although there is better news! Using the aw.def file from you in the form: EXPORTS aw_init aw_term aw_create aw_destroy etc... I modified it to have the following redefinition's: EXPORTS _aw_init=aw_init _aw_term=aw_term _aw_create=aw_create _aw_destroy=aw_destroy etc... I took this aw.def and implib'd it to aw.lib. Adding this lib to my project allowed a successful compile and a program that runs! The only bad thing is, I'm sure this will change with every revision of the sdk! |