|
Hello all!
I'm a VB and Assembly Programmer(Strange mix.. I know..). Well I need some help making a Dll project compile for use with VB. Below this message I will include instructions that I found for creating such a project. My problem is that I have a project (Speex.. i'm sure everyone is familiar) and I need to convert it not create a new one. Thank you in advance for the response! By the way on a scale of (1 - 10) my C++ skills are about 1.
Here is the project: http://downloads.us.xiph.org/releases/speex/speex-1.0.5.tar.gz
From what I understand all I need is:
1) A .DEF file
2) "Empty" Dll project (duno if you can change that after)
3) Include "ws2_32.lib"
*************************************************************************************
The info I found
*************************************************************************************
There have been projects I have been on in the past where there was certain functionality I needed but could not get from VB, or I had to do a complete workaround to get the functionality I could get from C++ very easily. In this tutorial I will show you how to create a C++ dll that you can call from VB. I figure instead of doing the norm, "HELLO WORLD", or "ADD NUMBER", routine I will show you how to resolve a domain name to an IP address and return that IP address back to VB, this is a little advanced for the beginner but if you have some C++ experience it wont be that bad.
For this example I will be using VC++ 6 so if you have that IDE then you will be right at home and in the case you do not use that IDE then just try to follow along and enjoy the ride!
Ok, you will first have to create a new dynamic link library project. After you create this project you will be prompted on what kind of DLL, just click empty.
After that is complete you will have to add the library ws2_32.lib to the project under project-> settings -> link -> object/modules library or the code below will not compile! Believe me when I tell you this as I had the fun of learning this the hard way and it was a nightmare.
You will now have to add three files to your project, the first being an implementation (.CPP) file, the second an interface/header (.H) file and the third a DEF (allows VB to be able to read the C++ dll function name) file.
Now lets add to the include files the function definitions for the header file. I called the header file for this demonstration c_dll_4_vb.h.
c_dll_4_vb.h
#include <windows.h>
#include <winsock.h>
// Function is used to resolve a domain name to an IP address.
// The return values are: -100 = Incorrect version of Winsock
// -200 = Cant resolve domain.
long __stdcall Resolve_Name_To_Ip
(char *pcDomainToResolve, char szReturnIP[500], int &iSize);
The function defined above will take three parameters:
• pcDomainToResolve - The name of the domain you are inquiring about.
• szReturnIP -The variable the IP address will be returned to you in.
• iSize - The length of IP address being returned without the padding.
Next you will need to add the implementation of the header file to the .CPP file. Remember that when you add the code to the .CPP file make sure you include the header file name (c_dll_4_vb.h).
c_dll_4_vb.cpp
#include "c_dll_4_vb.h"
long __stdcall Resolve_Name_To_Ip
(char *pcDomainToResolve, char szReturnIP[500], int &iSize)
{
WSADATA wsaData;
LPTSTR CompName = new char[255];
LPDWORD CompSize = new unsigned long(255);
struct sockaddr_in dest;
struct hostent *hp;
char *dest_ip;
unsigned int addr = 0;
strcpy(CompName,pcDomainToResolve);
if(WSAStartup(MAKEWORD(2,1), &wsaData) != 0)
{ WSACleanup();
return -100;
}
hp = gethostbyname(CompName);
if(!hp)
{ addr = inet_addr(CompName);
}
if((!hp) && (addr == INADDR_NONE))
{// Unable to resolve domain ip.
WSACleanup();
return -200;
}
hp = gethostbyname(CompName);
if(hp != NULL)
memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);
else
dest.sin_addr.s_addr = addr;
if(hp)
dest.sin_family = hp->h_addrtype;
else
dest.sin_family = AF_INET;
dest_ip = inet_ntoa(dest.sin_addr);
iSize = strlen(dest_ip);
// Allow the string to return to the proper size.
strncpy(szReturnIP, dest_ip, strlen(dest_ip));
dest_ip = NULL;
hp = NULL;
addr = 0;
dest.sin_family = NULL;
dest.sin_addr.s_addr = NULL;
dest.sin_addr.S_un.S_addr = NULL;
dest.sin_port = NULL;
delete [] CompName;
delete [] CompSize;
WSACleanup();
return 0;
}
Shew! Now that wasn't so bad. Ok, we have one more file to add data to but this one I swear is a breeze, this is the .DEF file. This file will let VB read the function names from the C++ dll. This is the most important file when working with C++ and VB because without it you will run into all kinds of errors.
So rather than just talking about it let see what this file looks like.
c_dll_4_vb.def
LIBRARY c_dll_4_vb
DESCRIPTION 'A C++ dll that can be called from VB'
EXPORTS
Resolve_Name_To_Ip @1
You have just completed the C++ dll. All that is left for you to do is compile the dll and it will be ready for use with VB.
So what are we waiting for lets get onto the VB stuff!
This is the easiest part of the demonstration so I wont go into detail as it is pretty much self explanatory.
Private Declare Function Resolve_Name_To_Ip _
Lib "[Add the path to the dll you just compiled]" _
(ByVal pcDomainToResolve As String, _
ByVal szReturnIP As String, _
ByRef iSize As Integer) As Long
Private Sub Form_Load()
Dim sIP As String
Dim iSize As Integer
Dim lRetVal As Long
Dim sDomain As String
sDomain = "www.yahoo.com"
sIP = String(20, "*")
lRetVal = Resolve_Name_To_Ip(sDomain, sIP, iSize)
MsgBox (Mid(sIP, 1, iSize))
End Sub
Well that just about wraps it up, but again, and I cannot stress it enough that if you run into trouble compiling the DLL make sure you have included the ws2_32.lib library in the project as explained above or you will get a ton of errors.
If you ever receive errors like, "error LNK2001: unresolved external symbol", you are most likely missing a required library. Just go ahead and add the missing library to the project and you will be good to go.
I hope this has helped you out!
***********************************************************************************
End if info
***********************************************************************************
|
|
|
|
|
Tinman0330 wrote: I'm a VB and Assembly Programmer(Strange mix.. I know..).
"Strange mix" is a definite understatement. I consider that to be the top (just put pieces toghether) and the bottom (actualy know how the pieces work). Assembly is one step below C (system-level) prgramming.
Now the ws2_32.lib (needed if using the ws2_32.dll) is related to Windows Sockets 2. Your code my use WinSockets, but that has nothing to do with your question. The .DEF is a resource file used to specify which functions you wish to export. The "@1" specifies an ordinal number (instead of name), incase you want to access the function via ordinal (never done that myself).
Use VC6 to create a simple .DLL (not an empty one), and read the comments that are generated. The notes will tell you how to export the functions without using a .DEF (which is a hold over for Win3.1 days). Play with it, add some functions, and see if you can access them from VB.
As a VB programmer you should know how to specify the VB equivalent of a function prototype, to access functions in a .DLL. If not there is a tool that comes with VB (there's a better one on the www somewhere) that will insert known Microsoft specific prototypes into your VB code. Look at the C prototypes in the VC6 header files and compare them to the VB equivalent prototypes.
Good Luck!
INTP
Every thing is relative...
|
|
|
|
|
Thank you for the reply! I created a new Dll project and looked at the examples of how to export functions. It looks like I am going to have to change each function in the project, and it is a large project. I was hoping that there would be a simple option for the linker or a short bit of code that could be added to it. Well i'm going to see if I can learn enough C++ to get a better understanding of this problem. If I am wrong about needing to change each function let me know. Thanks for the help!
|
|
|
|
|
I often run into such problem that I create a class successfully but I can't see it in the ClassView pane on the left. sometimes I can't see all of my classes. Reopenning the workspace sometimes can make the previouly hidden class appear and sometimes can not.
how come this happens? and how to prevent it?
Thank you very much!
|
|
|
|
|
I think you should install vc++ .
----------------------------
Jerry yu
Chinese
programming fans
|
|
|
|
|
I think you are using VC6.
Close the project, then try deleting the .NCB file and the .CLW files that are generated by the IDE.
If you delete the clw file, and then open ClassWizard, it will ask you about regenerating this file; say yes to it.
Also when the intellisense dies, it is useful to delete the .NCB file.
this is this.
|
|
|
|
|
|
EDIT: I think I figured out my problem, but if someone could still confirm. Basically I realized the classes that weren't showing up were just plain-old-c++ classes, and they were not derived from CObject (or more importantly CCmdTarget). At least I think that is the reason.
I'm also using VC6 and I have a number of classes that do not show in classwizard. I've tried the above a number of times and they simply do not appear. I've confirmed that the files containing these classes are listed as already in the project, but still nothing. Any idea how I get these added?
-- modified at 22:20 Tuesday 18th October, 2005
|
|
|
|
|
I am having a problem with a rich edit control not redrawing the frame
(border) properly when created over the top of a tab control. If the scroll
bar is shown and I delete all the text the scrollbar is removed and, for
some reason, so is the frame. Also the frame disappears if I minimise the
application and then restore it (no maximise option available). Has anybody
had any experience of this or a similar problem?
AxisFirst For Business
|
|
|
|
|
i have a toolbar made with the Win32 API
<br />
hwndTB = CreateWindowEx( 0, TOOLBARCLASSNAME, NULL, WS_CHILD | TBSTYLE_TOOLTIPS| WS_VISIBLE, <br />
0, 0, 0, 0, hWnd, (HMENU)IDC_TOOLBAR, GetModuleHandle(NULL), NULL );<br />
SendMessage( hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0 );<br />
<br />
<br />
HBITMAP hBMP = LoadBitmap( GetModuleHandle(NULL), (LPCTSTR)IDB_TBBUTTONS );<br />
TBADDBITMAP tbab = {NULL,(int)hBMP};<br />
SendMessage( hwndTB, TB_SETBITMAPSIZE, 0, (LPARAM)MAKELONG(16,16) );<br />
SendMessage( hwndTB, TB_ADDBITMAP, 8, (LPARAM)&tbab );<br />
<br />
<br />
TBBUTTON tbb[] = { <br />
{0,IDM_FILE_ADD,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,0},<br />
{1,IDM_FILE_EDIT,TBSTATE_ENABLED,TBSTYLE_BUTTON,1,1,1},<br />
{2,IDM_FILE_DELETE,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,2,2},<br />
{0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,0},<br />
{3,IDM_STUB_EDIT,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,3},<br />
{5,IDM_FILE_BUILD,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,4},<br />
{0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,0},<br />
{4,IDM_HELP_README,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,5}<br />
}; <br />
SendMessage( hwndTB, TB_ADDBUTTONS, 8, (LPARAM)&tbb );<br />
ShowWindow( hwndTB, SW_SHOW );
the bitmap(IDB_TBBUTTONS) looks like this
http://img422.imageshack.us/my.php?image=toolbarbuttons6gj.png[^]
so far it's working perfect, except i can't figure out how to set the mask, so the pink areas, are transparent..
can anyone help me out here?
|
|
|
|
|
I have not tried your code, but I find that the default generally helps:
The default background color of the toolbar created in VC applications have back color = RGB(192,192,192) Gray.
Try flood-filling the background of the toolbar with this color).
You can also use ImageLists. It seems to give the option of background masks.
this is this.
|
|
|
|
|
Hey,
I have a program that lists processes running on the system. For each Process I can get the Thread IDs of all the threads running in that process... Is it possible for me to use the thread ID for some process X to get that threads Module Name (like a loaded dll it uses) and/or Base address of the execution of that thread ?? Any help here would be appreciated.
Thanks,
Abhishek
|
|
|
|
|
Hi,
You need to use ToolHelp stuff.
See:
MODULENTRY32
Module32First
Module32Next
IMAGE_DOS_HEADER
IMAGE_NT_HEADER
ToolHelp32ReadProcessMemory
--
======
Arman
|
|
|
|
|
Hey Arman,
thanks for your reply... I have been using Thread32 and Process32 functions....how different would those be from Module32 .... What information must I give the module ?
Abhishek
|
|
|
|
|
Hey,
I had a look at the Module Function.....it gives me a list of the Modules that are being used by the process.....More specifically I need to find the start address of where a thread begins execution.
So I have a list of Threads .... how do I know the baseAddress of where they begin execution.
I don't know if you've used process explorer....When you right click on a process in Process Explorer and select properties, it pops up a tabbed window........Clicking on "Threads " in that window we get
a listing of Threads for the process in the form of Module!function....which basically gives the "Thread Start Address" and module name.
Regards ,
Abhishek
|
|
|
|
|
Have you checked the www.sysinternals.com website? I know they have process explorer there, not sure if they have source code for it or not.
.............................
There's nothing like the sound of incoming rifle and mortar rounds to cure the blues. No matter how down you are, you take an active and immediate interest in life.
Fiat justitia, et ruat cælum
|
|
|
|
|
hey,
I don't think sysinternals has the code for ProcessExplorer.......
Thanks
|
|
|
|
|
Hello,
I am having problem in passing pointers.
Here is a function:
static ULONG LoadParameter(lpInterface)
I need to pass this lpInterface pointer to another interface pointer called PDHINTERFACE(It has 4 parameters : ThreadID, input, output, size)
Thanks in advance
|
|
|
|
|
Exactly what is the problem?
Please post specific question.
Top ten member of C++ Expert Exchange.
http://www.experts-exchange.com/Cplusplus
|
|
|
|
|
Okay, so i have this CPropertySheet with multiple CPropertyPages. It gets data from a socket, that is sent up the line on a timing basis. Im having trouble taking this data, and displaying them into a CEdit display. The problem being, when i first execute my application, the current page that it starts out on is fine to update the display fields, but i get into trouble trying to update fields that arent on the active page. I've noticed, if i go real quick and click the tabs, it works fine there-after. So my question is this, Is there a method in either CPropertyPages or CPropertySheet, that will allow me to initialize all the dialog items? Or is there a way to code the clicking of each tab( which i feel is a poor way to handle this problem, but if it works so be it. ) I've thought of just having some global structures that the once i get the data from the socket, save it to the structure, set some update needed flag, and only check the update flags depending on which page im on, but this seems like alot work for a potentially easy solution ( which cant be that easy, cause i've spent some time on this. ) I appriciate any advice you might have, weather opinion or answer, thanks.
-Jader89
"There are 10 types of people, those who understand binary, and those who don't."
- Somebody, not me.
|
|
|
|
|
Another Note, I using the .construct() to create the pages, and adding them using addPage(). Then calling the doModal() method.
"There are 10 types of people, those who understand binary, and those who don't."
- Somebody, not me.
|
|
|
|
|
you can initialize each page when it comes active with CPropertyPage::OnSetActive, if you can initialize the pages when they get created in each page's OnInitDialog.
Maximilien Lincourt
Your Head A Splode - Strong Bad
|
|
|
|
|
When you decalre the pages before adding them to the porpertysheet set the PSP_PREMATURE flag on its flags. This will cause the sheet to create all the pages at the time it opens for the first time.
This should do exactly what you need
If you vote me down, my score will only get lower
|
|
|
|
|
Excatly what i was looking for, thanks a million!
"There are 10 types of people, those who understand binary, and those who don't."
- Somebody, not me.
|
|
|
|
|
|