Click here to Skip to main content
Click here to Skip to main content

Creating and Calling C Function DLL from .NET

By , 15 Sep 2004
 

Introduction

I will give an example of how to create a C DLL function and call it from VB.NET. It is simple but there are some tasks that you have to do.

First, create a C DLL Project. Use VC++ 6, from the File new project wizard, choose Win32 Dynamic-Link Library, click OK. Select an Empty DLL Project, because we just want to create a simple DLL. Click next.

Now add some files. From File new, select Files tab, select C++ Source File, name it for example Simple.c. Repeat the last step by creating Simple.def file.

Double click Simple.c and add the following code:

#include <WINDOWS.H>

      LPCSTR DisplayStringByVal(LPCSTR pszString)
      {
          return "Hallo apa kabar ";
      }

    void ReturnInParam(int* pnStan, char** pMsg)
    {
        long *buffer;
        char text[] = "Hallo ";
        char name[sizeof(*pMsg)];
         strcpy(name, *pMsg);
        *pnStan = *pnStan + 5;

        buffer = (long *)calloc(sizeof(text)+sizeof(*pMsg), sizeof( char ) );
        *pMsg = (char *)buffer;

        // do not free the buffer, because it will be used by the caller
        // free( buffer );
         strcpy(*pMsg, text);
         strcat(*pMsg, name);
      }

The first function simply returns the string "Hallo apa kabar" without processing anything. The second function adds "Hello" in front of the pMsg parameter and adds the pnStan parameter with 5. For example, if you call the second function from VB.NET code as below:

    <DllImport("E:\Temp\simple.dll", CallingConvention:="CallingConvention.Cdecl)"> _
    Private Shared Sub ReturnInParam(ByRef Stan As Integer, _
        ByRef Message As String)
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles Button1.Click
        Dim Num As Integer = 8
        Dim Message As String = "Harun"
        ReturnInParam(Num, Message)
        MessageBox.Show(Message)
    End Sub

After you call the function, the Num variable value is 13, and the message box will prompt Hello Harun.

Here is an explanation of some important things in the code. Let's see the function declaration in C:

void ReturnInParam(int* pnStan, char** pMsg)

The code...

int* pnStan

... indicates that you want to pass the parameter by reference, not by value. You can see this in the VB code:

Private Shared Sub ReturnInParam(ByRef Stan As Integer, _ ... 

The code...

char** pMsg 

... also indicates the same thing. The reason I put two asterisks (*) here is because .NET translates char* with a single quote as string and passes the parameter by value. So, if I want to pass the string by reference (or as a pointer), then I have to put another asterisk.

The rest of the C code is about adding 5 to pnStan and "Hello" at the beginning of pMsg. You must know C to understand the code.

Before you compile the C file, there is a final step that needs to be done:
Define the library and function in the Simple.def file as follows:

LIBRARY Simple
      DESCRIPTION 'Sample C DLL for use with .NET'
      EXPORTS
        DisplayStringByVal
        ReturnInParam

This tells VB where to locate the function Entry Point. If you don't provide this declaration, then you will get a message just like this:

An unhandled exception of type 'System.EntryPointNotFoundException' 
    occurred in Call_C_dll.exe

Additional information: Unable to find an entry point named ReturnInParam 
    in DLL E:\Temp\simple.dll.

Well, that's all, simple isn't it?

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

harunmip
Web Developer
Indonesia Indonesia
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generali get an error when i use the code in visual studio 2008membermlov838 Jan '11 - 7:27 
i get an error when i attempt to call the dll any suggestions?
"run-time check failure #2 - stack around the variable 'name' was corrupted"
Generalcall functions in a dll made with VB 2005 in a VB 2003 projectmembermurad198522 Nov '08 - 22:46 
Is there any way I can call functions in a dll made with VB 2005 in a VB 2003 project?
QuestionHow to call this functionmemberMuneer Safi18 Nov '08 - 2:35 
dear harunmip
 
i have this C function
 
int BII_Read_Transaction_Log (int option, int updateFlag, int maxEntries,
unsigned char *log)
 
*log A pointer to a buffer to hold the Transaction Log data.
 
how can use it in vb.net or c#
 
Please Help
Questionmemory leak???memberpradeeppatel5 Aug '07 - 19:54 
the memory is allocated here...
buffer = (long *)calloc(sizeof(text)+sizeof(*pMsg), sizeof( char ) );
 
if its not freed then how this memory will be deleted.
will it not be a memory leak??
 

Generalcall C code from C#memberBandoleiro11 Dec '06 - 0:35 
Hi,
I must create a DLL from C code, and reuse in C# webservices, I use VS 2005 .Net, but for my is the first time with windows and C# programming.
Can you help me?
 
Thank's
QuestionCalling From ServicedComponent?memberPyrinoc21 Nov '06 - 12:32 
Hi,
 
I'm trying to call code that looks very similar to this in a Com+ ServicedComponent class. The class that holds the C wrapper functions is in a separate class from the one that inherits ServicedComponent. However, if I try and call the functions I get a DLLNotFoundException. If I take out the ServicedComponent inheritance then it works perfectly fine. Is there a way to get around this? Thanks.
AnswerRe: Calling From ServicedComponent?memberEric Engler4 Jan '07 - 11:22 
It might be a folder issue. A win32 DLL must be in the path, or the same folder as the executing assembly. A COM+ class is executed from the Windows or System32 folder. Try coping the DLL into the System32 folder.
GeneralExtra Line needed in VB.NET codememberbetwulf25 Jul '06 - 11:21 
Don't forget to add the following line to the wrapper class in .NET:
 
Imports System.Runtime.InteropServices
Questiondll from c?memberjason_limwk2 Mar '06 - 22:10 
hi.. wana ask.. i am trying to do a c compiler in vb.. i mean.. i say an article teach me on how to create a .dll from visual c++ and rebuild it... so that i can get the .dll (as being told that it can be an agent to compile) and use it in my vb 6.0 coding...
however the tutorial still lacking of one part of description which i totally dono how to do it..
can anyone here please help on how to generate a dll in visual C++ so that in my vb coding i will be able to compile c coding ?
jasonlimwk@gmail.com
AnswerRe: dll from c?memberLunaSoft Inc.15 Aug '06 - 23:55 
It's Easy
In visual C
- Make DLL projects
- Mark function that you want to export from DLL with __declspec(dllexport) to make the compiler generate .DEF file (list of exported function)
example:
 
#include
__declspec(dllexport) void ExportMe() {
printf("Test!!\n");
}
 
- Then compile the project will be make a DLL file
- Invoke using VB.NET (nah, not VB 6.0 IT'S TOTALLY DIFFERENT) using
Imports System.Runtime.InteropServices
Public Class Whatever
_
Public Shared Sub ExportMe()
End Function
End Class
 
- Then Use on your sub Main
 
Module MainProg
Public Sub Main()
Whataver.ExportMe()
End Sub
End Module
 
Smile | :)
 
-- God will not change people fate until they change it themselves --

GeneralThanks for thatmemberRocketDude10 Dec '05 - 5:42 
Very nice code. Thanks!
 
Yeah dude, I rock!
GeneralDll Problemmembersrikar129 Aug '05 - 0:11 

url : = http://www.dotnet247.com/247reference/reply.aspx?s=607
 
(Type your message here)
 
Hi All,
 
I am calling a COM DLL which is written in VC++ from VB.Net application.
 
The thing is the method which handles operation with integer works fine.
The problem is with string.
 
I pass a parameter as string which remains empty after calling a method in dll.
 
This is that code from vb.net
iRetval = g_Contract.ContgetTotalNum()//Works fine.
Dim strBuffer as String
strBuffer = New string(" ",255)
g_Contract.CONTGetContractNumbers(2,strBuffer,Len(strBuffer)//strBuffer remains empty
cbo.Items.Add(strBuffer)//trying to populate the combo box.
 

The code in VC++ is
 
STDMETHODIMP CCOMDISBOBJECT::CONTGetContractNumbers(short sContract ,LPSTR lpzBuffer, long Buffersize)
.....
 
The ILDASM generated code is
CONTGetContractNumbers([in] int16 sContract,[in] string marshal(lpstr) lpzBuffer,[in] int32 Buffersize)
..............
 
I tried using stringbuilder also.I do not know if I have used it correctly,but it does not work.
I have also tried to create my own wrapper class.
But I am getting an error like 'Unable to find the entry point'
 
Please help me to get rid out this bug.
Thanks in advance.
 
bye.
gokul
--------------------------------
From: gokul narasimhan
 
hi
Generalnot rightsussAnonymous14 Sep '04 - 8:56 

If you pass an integer by ref, then a direct pointer is passed, because it's a blittable type, so no problems there.
 
But a string is another thing: if you pass a string by ref or as return type then on return the unmanaged string will be freed using FreeCoTaskMem, so the string must be allocated with AllocCoTaskMem.
 
The framework itself CAN NOT release any unmanaged memory other then (cotaskallocmem).
 
That why most string function pass a fixed size string + maxlength, so the unmanaged side doesn't need to allocate anything.
 
HTH,
greetings
 

GeneralCome onmembernorm.net8 Sep '04 - 0:19 
If this a a tutorial please explain P/Invoke it's uses and caveats, this could can be figured from anywhere.
 
I would recommend you and readers visit:
 
.NET Framework Developer's Guide
Interoperating with Unmanaged Code[^]
GeneralRe: Come onmemberhelitb8 Sep '04 - 0:42 
Well, like u said .NET explain the detail manual about consuming unmanaged code, but there are always some thing missing, or migth be difficult to find. I had to create some function in C and build it with VC6. I found several errors that I can not figure it out, yet. Finally I found some solution. Any way I will put additional notes in my article to make it better.
GeneralRe: Come onmembernorm.net8 Sep '04 - 0:50 
Probably the most complicated topics for P/Invoke for a new comer to .net, are:
 
#1 Marshaling Structures
#2 Marshaling Function Pointers
#3 Marshaling Handles
 
PInvoke.net[^] is also good place to visit.
 
And then you've got COM using CCW/RCW which is a whole new kettle of fish, best left for a another article/date.
 
Cheers

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 16 Sep 2004
Article Copyright 2004 by harunmip
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid