Hey all,
I have a program(using wxWidgets & MySql++ on MINGW) that has to have some Bluetooth Interaction with an Android App. The problem is that I am having trouble finding a framework(API) that would help me send,recieve data over Bluetooth with other applications. I searched and searched all over the Internet. But it was rather out in Vain...

And I have not used MSVC before so I was wondering if I could do something like this.
write the bluetooth portion of the project in MSVC and then create a dll/definition file out of it which i can connect to my MingW compiler or link it dynamically.

Is it possible? If it is possible, How do I go about it? I mean, I wish to have a good and clear understanding of what exactly I should be doing in order to make this work?

Recommended Answers

All 6 Replies

As far as I know, under windows, bluetooth is provided by native OS APIs (either Bluetooth-specific functions, or through Windows Sockets). Of course, it requires that you link against "Bthprops.lib". MinGW and GCC have work-arounds to be able to link to libraries not compiled with GCC, but it is most likely that this library is a C library and linking to it should be a breeze (otherwise, look up "linking MSVC .lib in MinGW", there are tutorials on the subject).

Making your own little wrapper in MSVC, and putting it into a dll is not going to be any easier than linking with Bthprops.lib in your MinGW/GCC project directly. You shouldn't need to "transform" the .lib into a dll. I have done this in the past (but can't exactly remember how) but it is very easy (just a linker flag to set, or a simple command-line to run).

I have just used the "reimp" tool and converted the lib into a def file. and from the def file I used dlltool to get a .a file. And have now linked it to my CodeBlocks IDE.

I thought of checking the compiler and fired up an example program
from http://www.winsocketdotnetworkprogramming.com/winsock2programming/winsock2advancedotherprotocol4p.html

#include <winsock2.h>
#include <ws2bth.h>
#include <BluetoothAPIs.h>
#include <cstdio>

#define DEFAULT_BUFLEN 512

typedef ULONGLONG bt_addr, *pbt_addr, BT_ADDR, *PBT_ADDR;

int main(int argc, char **argv)
{
    WSADATA wsd;
    SOCKET s;
    SOCKADDR_BTH sab;
    // Hard coded directly, got it from the receiver/server
    BT_ADDR aSddr = 0X001DD9EA24D8;
    int iResult;
    char *sendbuf = "Test data from client...";
    int recvbuflen = DEFAULT_BUFLEN;
    // Change the type accordingly for non-char data
    char recvbuf[DEFAULT_BUFLEN] = "";

    if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
    {
        printf("Unable to load Winsock! Error code is %d\n", WSAGetLastError());
        return 1;
    }
    else
        printf("WSAStartup() is OK, Winsock lib loaded!\n");

    s = socket (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
    if (s == INVALID_SOCKET)
    {
        printf ("Socket creation failed, error %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
   }
    else
        printf ("socket() looks fine!\n");
    memset (&sab, 0, sizeof(sab));
    sab.addressFamily  = AF_BTH;
    // Set the btAddr member to a BT_ADDR variable that
    // contains the address of the target device. App
    // can accept the device address as a string but must convert
    // the address and store it in a variable of type BT_ADDR.
    sab.btAddr = aSddr;
    // If the service identifier is available, then set the
    // serviceClassId member of SOCKADDR_BTH to the GUID of
    // the RFCOMM-based service. In this case, the client
    // performs an SDP query and then uses the resulting server channel.
    // sab.serviceClassId = nguiD;
   // Or If you want to use a hard-coded channel number, set the
    // port member of SOCKADDR_BTH to the server channel number (1-31)

    sab.port = 1;
    // Connect to the Bluetooth socket, created previously
    if (connect (s, (SOCKADDR *)&sab, sizeof(sab)) == SOCKET_ERROR)
    {
        printf("connect() failed with error code %d\n", WSAGetLastError ());
        closesocket(s);
        WSACleanup();
        return 1;
    }
    else
        printf("connect() should be fine!\n");

   iResult = send(s, sendbuf, (int)strlen(sendbuf), 0 );
    if (iResult == SOCKET_ERROR)
    {
        printf("send() failed with error code %d\n", WSAGetLastError());
        closesocket(s);
        WSACleanup();
        return 1;
    }
    else
    {
        printf("send() is OK!\n");
        printf("Bytes Sent: %d\n", iResult);
    }
    iResult = shutdown(s, SD_SEND);
    if (iResult == SOCKET_ERROR)
    {
        printf("shutdown() failed with error code %d\n", WSAGetLastError());
        closesocket(s);
        WSACleanup();
        return 1;
    }
    else
        printf("shutdown() is working!\n");

    do
    {
        iResult = recv(s, recvbuf, recvbuflen, 0);
        if (iResult > 0)
            printf(" %d Bytes received from sender\n", iResult);
        else if (iResult == 0)
            printf("Connection was closed by peer!\n");
        else
            printf("recv() failed with error code %d\n", WSAGetLastError());
    }
    while(iResult > 0);
    // Do all the cleanup
    if(closesocket(s) == 0)
       printf("closesocket() pretty fine!\n");
    if(WSACleanup () == 0)
        printf("WSACleanup() is OK!\n");
    return 0;

And when i test it, I get a flurry of errors.

C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\specstrings.h|11|error: sal.h: No such file or directory|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|851|error: #error Must define a target architecture.|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|1202|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|12880|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|13305|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winbase.h|2936|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winbase.h|2939|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winbase.h|2942|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winbase.h|3054|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winbase.h|3057|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winbase.h|3060|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winbase.h|3063|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winuser.h|3183|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winreg.h|1243|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winreg.h|1257|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\objbase.h|865|error: pasting "(" and "__drv_nop" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\oaidl.h|445|error: pasting "/" and "/" does not give a valid preprocessing token|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\oaidl.h|460|error: pasting "/" and "/" does not give a valid preprocessing token|
E:\test\try\socket_try.cpp|31|warning: integer constant is too large for 'long' type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|353|error: '__nullterminated' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|354|error: '__nullterminated' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|355|error: expected initializer before 'const'|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|356|error: '__nullterminated' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|357|error: expected initializer before 'const'|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|358|error: '__nullterminated' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|359|error: expected initializer before 'const'|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|361|error: '__nullterminated' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|362|error: expected initializer before 'const'|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|363|error: '__nullterminated' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|364|error: expected initializer before 'const'|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|366|error: '__possibly_notnullterminated' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|367|error: expected initializer before 'const'|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|368|error: '__possibly_notnullterminated' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|369|error: expected initializer before 'const'|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|421|error: '__nullterminated' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|422|error: '__nullterminated' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|423|error: expected initializer before 'const'|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|424|error: expected initializer before 'const'|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|425|error: '__nullterminated' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|427|error: '__nullterminated' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|428|error: expected initializer before 'const'|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|430|error: '__possibly_notnullterminated' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|431|error: expected initializer before 'const'|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|471|error: 'LPSTR' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|472|error: 'LPCSTR' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|473|error: 'PZZSTR' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|474|error: 'PCZZSTR' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|475|error: 'PNZCH' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|476|error: 'PCNZCH' does not name a type|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|542|error: typedef '__success' is initialized (use decltype instead)|
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\winnt.h|542|error: expected primary-expression before 'return'|
||More errors follow but not being shown.|
||Edit the max errors limit in compiler options...|
||=== Build finished: 50 errors, 1 warnings ===|

What Am I doing wrong??

Aaargh! Microsoft strikes again!

You did things correctly. The problem with all those things (many of which start with double underscore) is that Microsoft cannot restrain themselves from using non-standard, MSVC-specific language extensions even in their SDK headers.

In this case, I would recommend that you do wrap your bluetooth calls in a piece of code that you compile with MSVC. But, that piece of code doesn't need to be a dll (could be a .lib and using the same process to link it in MinGW). Remember to expose only a C interface (extern "C").

Thanks Mike, Now I am in a dilemma to either port my Existing project into MSVC. This would involve configuring MYSQL++ and WxWidgets to it.

Or

As mentioned above, write an implementation in MsVc and then port it to link it back to the MINGW.

As Mike has suggested, I have come up with this small wrapper for most of the functions that I will be needing. I am not exactly sure if the code I have written is correct.I didn't even test it before I posted it here.

ALTHOUGH I managed to write a 'C' file with extern C

Here is what I have framed my code as.

/**************************************************************************************************
	
File: Bth_Frame.h	
	
	Framework for the BLUETOOTH Socket Layer. to move it onto the MINGW compiler 
	----------------------------------------------------------------------------
		Created By : Susheel Kumar				Date: 28-05-2011
***************************************************************************************************/


#include <WinSock2.h>
#include <ws2bth.h>
#include <InitGuid.h>

// -------------------------------------Constants -------------------------------------------------
#define BUFFER_SIZE 200

int CreateSocket(); //Creates a Listening Socket to accept a Single Connection and Closes. Returns a Socket.
int ReadFromSocket(int _sock_c, char* data); // Reads Basic Data from a Socket passed to it. 
int WriteToSocket( int _sock_c, char* data, int size); // Write to Socket Works on the Same Principles of ReadFromSocket.
void CloseSocket( int _sock_c);	// The Close Socket Closes the Socket which was returned as Output of CreateSocket.
void CloseConnection(); //Calls WSACleanup();

And here is the file that follows, Implementation file.

/**************************************************************************************************
	
File: Bth_Frame.c	
	
	Framework for the BLUETOOTH Socket Layer. to move it onto the MINGW compiler 
	----------------------------------------------------------------------------
		Created By : Susheel Kumar				Date: 28-05-2011
***************************************************************************************************/

#include "Bth_Frame.h"
extern "C" {
// This here should also be hard coded into the applications that need to communicate with the	App (Ie: The Android App Client)
// {A167AE48-1AE5-4096-9AE2-AB4FA24B0DEB}
DEFINE_GUID(my_Guid,0xa167ae48, 0x1ae5, 0x4096, 0x9a, 0xe2, 0xab, 0x4f, 0xa2, 0x4b, 0xd, 0xeb);




/***********************************************************************************************

The Main Goal here is to create a Server that will act as an interface for the actual code 
-------------------------------------------------------------------------------------------


-1										WSASTARTUP() failed
-2										Creation of SOCKET (sock_s) failed.
-3										Binding of SOCKET (sock_s) failed.
-4										Listening of SOCKET (sock_s) failed.
-5										Accept of Socket (sock_s , sock_c ) failed.
************************************************************************************************/


int CreateSocket()
{
    SOCKET sock_s, sock_c;
	WSADATA	wsa;
	int val,ilen;
	SOCKADDR_BTH add1,add2;
	if ( WSAStartup( MAKEWORD(2,2),&wsa) != 0 )
	{
		return -1;
	}

		sock_s =socket( AF_BTH,SOCK_STREAM,BTHPROTO_RFCOMM );
		if ( sock_s == INVALID_SOCKET )
			return -2;
		
		//Clearing the SOCKADDR_BTH variable
		memset(&add1,0,sizeof(add1));
		
		add1.addressFamily=AF_BTH;
		add1.serviceClassId=my_Guid;

		val=bind(sock_s, (SOCKADDR*) &add1 ,sizeof(add1));
		if(val != 0 )
		{
			closesocket(sock_s);
			return -3;
		}

		if( listen(sock_s,1) != 0 )
		{
			closesocket(sock_s);
			return -4;
		}
		
		ilen=sizeof(add2);
		sock_c = accept(sock_s, (SOCKADDR*) &add2 , &ilen );
		if (sock_c == INVALID_SOCKET)
		{
			closesocket(sock_c);
			return -5;
		}

			closesocket(sock_s);	
			return sock_c;
}


/*************************************************************************************************
	Data is read from the socket. 
	Data structure will be like this
	--------------------------------
	<Number of Bytes> < Data > <END>
	--------------------------------

	on the first request, the Mingw will look at the 
	number of bytes being sent, then on the basis of that
	it will determine whether to call additional reads,
	the return values will also indicate what exactly it should do.

	Note: It is necessary to free the space of the pointer returned by read.

	RET_tYPE			INDICATION
	 a > 0					Read Success 
	-1					Read failure ( Socket is Closed )
	-2					Complete READ FAILURE.
*************************************************************************************************/
int ReadFromSocket( int _sock_c , char *data)
{
	int a;
	SOCKET sock_c = (SOCKET) _sock_c;
	data= new char[ BUFFER_SIZE ];
	a= recv(sock_c,data,BUFFER_SIZE,0);
	if (a>0)
		return a;	// Recieved data 
	else if (a == 0)
		return -1;	// Socket on the other end closed
	else 
		return -2; // Socket Error
}

/****************************************************************************************************
	Wrapper for writing data into the Socket.
	-----------------------------------------

	returns 
	 a					Success ( a bytes sent )
	-1					Error.

*****************************************************************************************************/

int WriteToSocket( int _sock_c , char *data, int size)
{
	int a;
	SOCKET sock_c = (SOCKET) _sock_c;
	a= send (sock_c,data,size,0);
	if (a==SOCKET_ERROR)
		return -1;
	else
		return a;
}
//*******************************************************************************************************
void CloseSocket( int _sock_c )
{
	SOCKET sock_c = (SOCKET ) _sock_c;
	closesocket(sock_c);
}
//*******************************************************************************************************
void CloseConnection ( )
{
	WSACleanup();
}
//*********************************************************************************************************

}// End of Extern "c" linkage.

Will this work?

You need to put those #include statements for winsock and win2bth into the .c file. This is because you are going to need to #include your header file into your MinGW project, which will drag along the bluetooth windows includes that are causing problems with GCC. You don't need those includes to create your header file, so just put them in the .c file.

Second, you need to declare your functions in your header file with the extern "C" as well (in fact, that's where it matters the most).

Third, you probably want to compile this as a small DLL, so you also need to declare those functions as exported/imported, as so:

#ifdef COMPILING_DLL_MODULE
#define DLLFUNCTION __declspec(dllexport)
#else
#define DLLFUNCTION __declspec(dllimport)
#endif

extern "C" int DLLFUNCTION CreateSocket();

So that when you compile the DLL, you set the #define COMPILING_DLL_MODULE, and when you use your DLL, you use the same header, but without defining COMPILING_DLL_MODULE (thus, causing the functions to be imported).

To know if your code is working, you should first use this code with a simple main() function to test that you can connect / read / write / close successfully. Do that test on MSVC without compiling this into a DLL, that will be easier for debugging if there are any trouble. Once you know that your code works, compile it as a DLL and import it to your MinGW project.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.