|
Archives
D Programming
DD.gnu digitalmars.D digitalmars.D.bugs digitalmars.D.dtl digitalmars.D.dwt digitalmars.D.announce digitalmars.D.learn digitalmars.D.debugger C/C++ Programming
c++c++.announce c++.atl c++.beta c++.chat c++.command-line c++.dos c++.dos.16-bits c++.dos.32-bits c++.idde c++.mfc c++.rtl c++.stl c++.stl.hp c++.stl.port c++.stl.sgi c++.stlsoft c++.windows c++.windows.16-bits c++.windows.32-bits c++.wxwindows digitalmars.empire digitalmars.DMDScript |
c++.windows.32-bits - 32 bit dll compiling part 2
This is 32-bit DLL compiling.
From kiviapaja hotmail.com
Why next example fails?
dmc -mn -WD ../gwinsock.cpp -w -D__DMC__ -Dgwinsock_main kernel32.lib
user32.lib gdi32.lib comdlg32.lib wsock32.lib > err2.txt
link gwinsock,,,kernel32+user32+gdi32+comdlg32+wsock32,gwinsock/noi;
OPTLINK (R) for Win32 Release 7.50B1
Copyright (C) Digital Mars 1989 - 2001 All Rights Reserved
OPTLINK : Warning 148: USE16/USE32 Mismatch : DGROUP
F:\DM\BIN\..\lib\SNN.lib(dllstart)
Error 83: Illegal frame on start address
OPTLINK : Warning 174: 32-bit Segments Inappropriate for 16-bit Segmented
output
gwinsock.obj(gwinsock)
Error 116: NEAR call to IMPORT at Relative 00025H from
Segment _TEXT
FRAME = Frame of Group FLAT 0000
TARGET = External Symbol _WSAStartup 8 00000H
FIXUPP Type = 32-bit Conditional JMP
--- errorlevel 2
Is this from source code or .def
My def is like this:
LIBRARY gwinsock
DESCRIPTION 'GWinSock -- socket wrapper dll'
EXETYPE WINDOWS
EXPORTS
_gensock_close 1
_gensock_connect 2
_gensock_getchar 3
_gensock_gethostname 4
_gensock_put_data 5
_gensock_put_data_buffered 6
_gensock_put_data_flush 7
My source is like this
------- gwinsock.cpp ------------
// -*- C++ -*-
// generic socket DLL, winsock version
// disclaimer: a C programmer wrote this.
// $Id: gensock.cpp 1.151 2004/12/25 22:07:10 NooN Exp $
// $Id: gensock.cpp 1.15 1994/11/23 22:38:10 rushing Exp $
#include <windows.h>
#include <string.h>
#include <ctype.h>
extern "C"
{
#include <winsock.h>
#include "gwinsock.h"
}
#ifdef _DEBUG
#ifndef __BORLANDC__
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#else
#include <stdlib.h>
#endif
#else
#include <stdlib.h>
#endif
//MDS increased buffer from 512 19991214
#define SOCKET_BUFFER_SIZE 1500
// This is for NT
HANDLE dll_module_handle;
#define GET_CURRENT_TASK dll_module_handle
#define TASK_HANDLE_TYPE HANDLE
//
//
-------------------------------------------------------------------------
--
// container for a buffered SOCK_STREAM.
class connection
{
private:
SOCKET the_socket;
char * in_buffer;
char * out_buffer;
unsigned int in_index;
unsigned int out_index;
unsigned int in_buffer_total;
unsigned int out_buffer_total;
unsigned int last_winsock_error;
TASK_HANDLE_TYPE owner_task;
fd_set fds;
struct timeval timeout;
public:
connection (void);
~connection (void);
int get_connected (char far * hostname, char far *
service);
SOCKET get_socket(void) { return (the_socket); }
TASK_HANDLE_TYPE get_owner_task(void) { return (owner_task); }
int get_buffer(int wait);
int close (void);
int getchar (int wait, char far * ch);
int put_data (char far * data, unsigned long length);
int put_data_buffered (char far* data, unsigned long
length);
int put_data_flush (void);
};
//
//-----------------------------------------------------------------------
----
// we keep lists of connections in this class
class connection_list
{
private:
connection * data;
connection_list * next;
public:
connection_list (void);
~connection_list (void);
void push (connection & conn);
// should really use pointer-to-memberfun for these
connection * find (SOCKET sock);
int how_many_are_mine (void);
void remove (socktag sock);
};
connection_list global_socket_list;
int network_initialized;
//int init_winsock (void);
//void deinit_winsock (void);
//
//
//
#ifdef _DEBUG
void complain (char * message)
{
OutputDebugString (message);
}
#else
void complain (char * message)
{
MessageBox (NULL, message, "GWINSOCK.DLL Error", MB_OK|MB_ICONHAND);
}
#endif
//-----------------------------------------------------------------------
----
//
//
int init_winsock(void)
{
int retval;
WSADATA winsock_data;
WORD version_required = 0x0101; // Version 1.1
retval = WSAStartup (version_required, &winsock_data);
switch (retval)
{
case 0:
// successful
break;
case WSASYSNOTREADY:
return (ERR_SYS_NOT_READY);
break;
case WSAEINVAL:
return (ERR_EINVAL);
break;
case WSAVERNOTSUPPORTED:
return (ERR_VER_NOT_SUPPORTED);
break;
}
network_initialized = 1;
return (0);
}
void deinit_winsock(void)
{
network_initialized = 0;
WSACleanup();
}
connection::connection (void)
{
the_socket = 0;
in_index = 0;
out_index = 0;
in_buffer_total = 0;
out_buffer_total = 0;
in_buffer = 0;
in_buffer = new char[SOCKET_BUFFER_SIZE];
out_buffer = new char[SOCKET_BUFFER_SIZE];
last_winsock_error = 0;
}
connection::~connection (void)
{
delete [] in_buffer;
// NooN
delete [] out_buffer;
// NooN ^^
}
int gensock_is_a_number (char far* string)
{
while (*string)
{
if (!isdigit (*string))
{
return (0);
}
string++;
}
return (1);
}
//
//
-------------------------------------------------------------------------
--
//
int connection::get_connected (char FAR * hostname, char FAR * service)
{
struct hostent FAR * hostentry;
struct servent FAR * serventry;
unsigned long ip_address;
struct sockaddr_in sa_in;
int our_port;
int nott = 0;
int retval, err_code;
unsigned long ioctl_blocking = 1;
char message[512];
// if the ctor couldn't get a buffer
if (!in_buffer || !out_buffer)
return (ERR_CANT_MALLOC);
// --------------------------------------------------
// resolve the service name
//
// If they've specified a number, just use it.
if (gensock_is_a_number (service))
{
char far* tail;
our_port = (int) strtol (service, &tail, 10);
if (tail == service)
{
return (ERR_CANT_RESOLVE_SERVICE);
}
else
{
our_port = htons (our_port);
}
}
else
{
// we have a name, we must resolve it.
serventry = getservbyname (service, (LPSTR)"tcp");
if (serventry)
our_port = serventry->s_port;
else
{
retval = WSAGetLastError();
// Chicago beta is throwing a WSANO_RECOVERY here...
if ((retval == WSANO_DATA) || (retval == WSANO_RECOVERY))
{
return (ERR_CANT_RESOLVE_SERVICE);
}
else
{
return (retval - 5000);
}
}
}
// --------------------------------------------------
// resolve the hostname/ipaddress
//
if ((ip_address = inet_addr (hostname)) != INADDR_NONE)
{
sa_in.sin_addr.s_addr = ip_address;
}
else
{
if ((hostentry = gethostbyname(hostname)) == NULL)
{
return (ERR_CANT_RESOLVE_HOSTNAME);
}
sa_in.sin_addr.s_addr = *(long far *)hostentry->h_addr;
#if 0
{
OutputDebugString(inet_ntoa(sa_in.sin_addr));
}
#endif
}
// --------------------------------------------------
// get a socket
//
if ((the_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
return (ERR_CANT_GET_SOCKET);
}
sa_in.sin_family = AF_INET;
sa_in.sin_port = our_port;
// set socket options. DONTLINGER will give us a more graceful
disconnect
// MDS yes, and also terminate our connections before the last
command
// has been completely sent causing abnormal terminations on the
receiving
// side!
// From www.lcg.org/sock-faq
// "... SO_LINGER seems to be required to guarantee delivery of all
data."
//20000410
#if 0
setsockopt(the_socket,SOL_SOCKET,SO_DONTLINGER,(char *) ¬t,
sizeof(nott));
#endif
// get a connection
if ((retval = connect (the_socket,
(struct sockaddr *)&sa_in,
sizeof(struct sockaddr_in))==SOCKET_ERROR))
{
switch ((err_code = WSAGetLastError()))
{
// twiddle our thumbs until the connect succeeds
case WSAEWOULDBLOCK:
break;
case WSAECONNREFUSED:
return (ERR_CONNECTION_REFUSED);
break;
default:
wsprintf(message, "unexpected error %d from winsock\n",
err_code);
complain(message);
return (ERR_CANT_CONNECT);
break;
}
}
owner_task = GET_CURRENT_TASK;
// Make this a non-blocking socket
ioctlsocket (the_socket, FIONBIO, &ioctl_blocking);
// make the FD_SET and timeout structures for later operations...
FD_ZERO (&fds);
FD_SET (the_socket, &fds);
// normal timeout, can be changed by the wait option.
timeout.tv_sec = 30;
timeout.tv_usec = 0;
return (0);
}
//
//-----------------------------------------------------------------------
----
//
// The 'wait' parameter, if set, says to return WAIT_A_BIT
// if there's no data waiting to be read.
int connection::get_buffer(int wait)
{
int retval;
int bytes_read = 0;
unsigned long ready_to_read = 0;
// Use select to see if data is waiting...
FD_ZERO (&fds);
FD_SET (the_socket, &fds);
// if wait is set, we are polling, return immediately
if (wait)
{
timeout.tv_sec = 0;
}
else
{
timeout.tv_sec = 30;
}
if ((retval = select (0, &fds, NULL, NULL, &timeout))
== SOCKET_ERROR)
{
char what_error[256];
int error_code = WSAGetLastError();
if (error_code == WSAEINPROGRESS && wait)
{
return (WAIT_A_BIT);
}
wsprintf (what_error,
"connection::get_buffer() unexpected error from select: %d",
error_code);
complain (what_error);
}
// if we don't want to wait
if (!retval && wait)
{
return (WAIT_A_BIT);
}
// we have data waiting...
bytes_read = recv (the_socket,in_buffer,SOCKET_BUFFER_SIZE,0);
// just in case.
if (bytes_read == 0)
{
// connection terminated (semi-) gracefully by the other side
return (ERR_NOT_CONNECTED);
}
if (bytes_read == SOCKET_ERROR)
{
char what_error[256];
int ws_error = WSAGetLastError();
switch (ws_error) {
// all these indicate loss of connection (are there more?)
case WSAENOTCONN:
case WSAENETDOWN:
case WSAENETUNREACH:
case WSAENETRESET:
case WSAECONNABORTED:
case WSAECONNRESET:
return (ERR_NOT_CONNECTED);
break;
case WSAEWOULDBLOCK:
return (WAIT_A_BIT);
break;
default:
wsprintf (what_error,
"connection::get_buffer() unexpected error: %d",
ws_error);
complain (what_error);
}
}
// reset buffer indices.
in_buffer_total = bytes_read;
in_index = 0;
return (0);
}
//
//-----------------------------------------------------------------------
----
// get a character from this connection.
//
int connection::getchar(int wait, char FAR * ch)
{
int retval;
if (in_index >= in_buffer_total)
{
if ((retval = get_buffer(wait)))
return (retval);
}
*ch = in_buffer[in_index++];
return (0);
}
//
//-----------------------------------------------------------------------
----
// FIXME: should try to handle the fact that send can only take
// an int, not an unsigned long.
int connection::put_data (char far* data, unsigned long length)
{
int num_sent;
int retval;
FD_ZERO (&fds);
FD_SET (the_socket, &fds);
timeout.tv_sec = 30;
while (length > 0)
{
if ((retval = select (0, NULL, &fds, NULL, &timeout)) ==
SOCKET_ERROR)
{
char what_error[256];
int error_code = WSAGetLastError();
wsprintf (what_error,
"connection::put_data() unexpected error from select:
%d",
error_code);
complain (what_error);
}
num_sent = send (the_socket,
data,
length > 1024 ? 1024 : (int)length,
0);
if (num_sent == SOCKET_ERROR)
{
char what_error[256];
int ws_error = WSAGetLastError();
switch (ws_error)
{
// this is the only error we really expect to see.
case WSAENOTCONN:
return (ERR_NOT_CONNECTED);
break;
// seems that we can still get a block
case WSAEWOULDBLOCK:
case WSAEINPROGRESS:
break;
default:
wsprintf (what_error,
"connection::put_data() unexpected error from send():
%d",
ws_error);
complain (what_error);
return (ERR_SENDING_DATA);
}
}
else
{
length -= num_sent;
data += num_sent;
}
}
return (0);
}
//
//
// buffered output
//
int connection::put_data_buffered (char far* data, unsigned long length)
{
unsigned int sorta_sent = 0;
int retval;
while (length)
{
if ((out_index + length) < SOCKET_BUFFER_SIZE)
{
// we won't overflow, simply copy into the buffer
memcpy (out_buffer + out_index, data, (size_t) length);
out_index += (unsigned int) length;
length = 0;
}
else
{
unsigned int orphaned_chunk = SOCKET_BUFFER_SIZE - out_index;
// we will overflow, handle it
memcpy (out_buffer + out_index, data, orphaned_chunk);
// send this buffer...
if ((retval = put_data (out_buffer, SOCKET_BUFFER_SIZE)))
{
return (retval);
}
length -= orphaned_chunk;
out_index = 0;
data += orphaned_chunk;
}
}
return (0);
}
int connection::put_data_flush (void)
{
int retval;
if ((retval = put_data (out_buffer, out_index)))
return (retval);
else
out_index = 0;
return(0);
}
//
//-----------------------------------------------------------------------
----
//
int connection::close (void)
{
if (closesocket(the_socket) == SOCKET_ERROR)
return (ERR_CLOSING);
else
return (0);
}
connection_list::connection_list (void)
{
next = 0;
}
connection_list::~connection_list(void)
{
delete data;
}
// add a new connection to the list
void connection_list::push (connection & conn)
{
connection_list * new_conn;
new_conn = new connection_list();
new_conn->data = data;
new_conn->next = next;
data = &conn;
next = new_conn;
}
int connection_list::how_many_are_mine(void)
{
TASK_HANDLE_TYPE current_task = GET_CURRENT_TASK;
connection_list * iter = this;
int num = 0;
while (iter->data)
{
if (iter->data->get_owner_task() == current_task)
num++;
iter = iter->next;
}
return (num);
}
// find a particular socket's connection object.
connection * connection_list::find (SOCKET sock)
{
connection_list * iter = this;
while (iter->data)
{
if (iter->data->get_socket() == sock)
return (iter->data);
iter = iter->next;
}
return (0);
}
void connection_list::remove (socktag sock)
{
// at the end
if (!data)
return;
// we can assume next is valid because
// the last node is always {0,0}
if (data == sock)
{
delete data;
data = next->data;
next = next->next; // 8^)
return;
}
// recurse
next->remove(sock);
}
//
//
-------------------------------------------------------------------------
--
// global variables (shared by all DLL users)
//
//-----------------------------------------------------------------------
----
//
extern "C"
{
INT WINAPI DllMain (HANDLE hInst, ULONG reason_called,LPVOID
reserved)
{
switch (reason_called)
{
case DLL_PROCESS_ATTACH:
// init
dll_module_handle = hInst;
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
return (1);
}
//
-------------------------------------------------------------------------
--
// C/DLL interface
//
int GENSOCK_EXPORT CELLBACK gensock_connect (char FAR * hostname,
char FAR * service,
socktag FAR * pst)
{
int retval;
connection * conn = new connection;
if (!conn)
return (ERR_INITIALIZING);
// if this task hasn't opened any sockets yet, then
// call WSAStartup()
if (global_socket_list.how_many_are_mine() < 1)
init_winsock();
global_socket_list.push(*conn);
if ((retval = conn->get_connected (hostname, service)))
{
gensock_close(conn);
*pst = 0;
return (retval);
}
*pst = (void FAR *) conn;
return (0);
}
//
//
//
int GENSOCK_EXPORT CELLBACK gensock_getchar (socktag st, int wait, char
FAR * ch)
{
connection * conn;
int retval = 0;
conn = (connection *) st;
if (!conn)
return (ERR_NOT_A_SOCKET);
if ((retval = conn->getchar(wait, ch)))
return (retval);
else
return (0);
}
//-----------------------------------------------------------------------
----
//
//
int GENSOCK_EXPORT CELLBACK
gensock_put_data (socktag st, char FAR * data, unsigned long length)
{
connection * conn;
int retval = 0;
conn = (connection *) st;
if (!conn)
return (ERR_NOT_A_SOCKET);
if ((retval = conn->put_data(data, length)))
return (retval);
return (0);
}
//-----------------------------------------------------------------------
----
//
//
int GENSOCK_EXPORT CELLBACK gensock_put_data_buffered (socktag st, char
FAR * data, unsigned long length)
{
connection * conn;
int retval = 0;
conn = (connection *) st;
if (!conn)
return (ERR_NOT_A_SOCKET);
if ((retval = conn->put_data_buffered (data, length)))
return (retval);
return (0);
}
//-----------------------------------------------------------------------
----
//
//
int GENSOCK_EXPORT CELLBACK gensock_put_data_flush (socktag st)
{
connection * conn;
int retval = 0;
conn = (connection *) st;
if (!conn)
return (ERR_NOT_A_SOCKET);
if ((retval = conn->put_data_flush() ))
return (retval);
return (0);
}
//-----------------------------------------------------------------------
----
//
//
int GENSOCK_EXPORT CELLBACK gensock_gethostname (char FAR * name, int
namelen)
{
int retval;
if ((retval = gethostname(name, namelen)))
{
return (retval - 5000);
}
else return (0);
}
int GENSOCK_EXPORT CELLBACK gensock_close (socktag st)
{
connection * conn;
int retval;
conn = (connection *) st;
if (!conn)
return (ERR_NOT_A_SOCKET);
if ((retval = conn->close()))
return (retval);
global_socket_list.remove((connection *)st);
if (global_socket_list.how_many_are_mine() < 1)
{
deinit_winsock();
}
return (0);
}
} // extern "C"
---------gwinsock.cpp------------
---------- gwinsock.h------------
and gwinsock.h
/* $Id: gensock.h 1.81 2004/12/25 22:06:11 NooN Exp $ */
/* $Id: gensock.h 1.8 1995/01/25 23:28:11 rushing Exp $ */
#define ERR_CANT_MALLOC 4001
#define ERR_SENDING_DATA 4002
#define ERR_INITIALIZING 4003
#define ERR_VER_NOT_SUPPORTED 4004
#define ERR_EINVAL 4005
#define ERR_SYS_NOT_READY 4006
#define ERR_CANT_RESOLVE_HOSTNAME 4007
#define ERR_CANT_GET_SOCKET 4008
#define ERR_READING_SOCKET 4009
#define ERR_NOT_A_SOCKET 4010
#define ERR_BUSY 4011
#define ERR_CLOSING 4012
#define WAIT_A_BIT 4013
#define ERR_CANT_RESOLVE_SERVICE 4014
#define ERR_CANT_CONNECT 4015
#define ERR_NOT_CONNECTED 4016
#define ERR_CONNECTION_REFUSED 4017
#define ERR_NO_ERROR_CODE -5000
/* this is returned by misbehaving stacks that
* fail, but don't set an error code
*/
typedef void * socktag;
// #ifdef __BORLANDC__
#ifdef __BC45__
#define CELLBACK CALLBACK
#define GENSOCK_EXPORT __export
#endif
#ifdef __BC55__
#define CELLBACK CALLBACK
#define GENSOCK_EXPORT __export
#endif
#ifdef __BC600__
#define CELLBACK CALLBACK
#define CELLBACK CALLBACK
#define GENSOCK_EXPORT __export
/*
#ifdef gwinsock_main
#define GENSOCK_EXPORT __declspec(dllexport)
#else
#define GENSOCK_EXPORT __declspec(dllimport)
#endif
*/
#endif
// #endif // borlandc
#ifdef __DMC__
#define CELLBACK
#ifdef gwinsock_main
#define GENSOCK_EXPORT __declspec(dllexport)
#else
#define GENSOCK_EXPORT __declspec(dllimport)
#endif
#endif
#ifdef __WATCOM__
#define CELLBACK CALLBACK
#ifdef gwinsock_main
#define GENSOCK_EXPORT __declspec(dllexport)
#else
#define GENSOCK_EXPORT __declspec(dllimport)
#endif
#endif
#ifdef __GCC__
#define CELLBACK
#ifdef gwinsock_main
#define GENSOCK_EXPORT __declspec(dllexport)
#else
#define GENSOCK_EXPORT __declspec(dllimport)
#endif
#endif
#ifdef __MSVC__
#define CELLBACK CALLBACK
#ifdef gwinsock_main
#define GENSOCK_EXPORT __declspec(dllexport)
#else
#define GENSOCK_EXPORT __declspec(dllimport)
#endif
//#define GENSOCK_EXPORT FAR PASCAL
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* function prototypes */
int GENSOCK_EXPORT CELLBACK gensock_connect (char * hostname,
char * service,
socktag * pst);
int GENSOCK_EXPORT CELLBACK gensock_getchar (socktag st,
int wait,
char * ch);
int GENSOCK_EXPORT CELLBACK gensock_put_data (socktag st,
char * data,
unsigned long length);
int GENSOCK_EXPORT CELLBACK gensock_close (socktag st);
int GENSOCK_EXPORT CELLBACK gensock_gethostname (char * name, int
namelen);
int GENSOCK_EXPORT CELLBACK gensock_put_data_buffered (socktag st,
char * data,
unsigned long length);
int GENSOCK_EXPORT CELLBACK gensock_put_data_flush (socktag st);
#ifdef __cplusplus
}
#endif
------------------- gwinsock.h -------------
Can someone help this?
Janne Naukkarinen
kiviapaja hotmail.com
Jan 14 2004
EXETYPE WINDOWS specifies a 16 bit output. Use EXETYPE NT instead. See www.digitalmars.com/ctg/ctgDefFiles.html "Janne Naukkarinen" <kiviapaja hotmail.com> wrote in message news:bu4bkg$299g$1 digitaldaemon.com... Jan 18 2004
|