Click here to Skip to main content
15,889,877 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
i have created dll in vc++
init_set(char *)

takes char *

C#
extern "C" MYDLL_API int init_set(char*);
extern "C" MYDLL_API int init_valid();


in c# i want to pass an string to init_set().


C#
[DllImport("MYDLL.dll")]
public static extern int init_set(char[] s);

[DllImport("MYDLL.dll")]
public static extern int init_valid();


in main

C#
static void Main(string[] args)
       {
           string st = "Quad127";
           char[] s = st.ToCharArray();

           init();
            init_set(s);


all void function runs but this gives message
An unhandled exception of type 'System.EntryPointNotFoundException' occurred in usedll.exe

Additional information: Unable to find an entry point named 'init_set' in DLL 'MYDLL.dll'.
Posted
Updated 12-Nov-11 0:15am
v3
Comments
Richard MacCutchan 12-Nov-11 6:20am    
What is the value of MYDLL_API in your build of the DLL. Also show the actual code for the init_set() function.
01.mandar 14-Nov-11 8:23am    
int init_set(char* id)
{
char fire[100]={0};

strcat(fire,"AT+AIPO=");
strcat(fire,id);
// some more strcat parameters

if(sp_writer(fire))
return 0;
else
return 1;
}
Richard MacCutchan 14-Nov-11 12:12pm    
I suspect there is still some problem with your build process; check that you are correctly exporting your function names. As I asked above, what is the value of MYDLL_API in your build of the dll. You should also be able to check whether your functions are being exported correctly by using Dependency Walker.
01.mandar 15-Nov-11 1:59am    
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif

extern "C" MYDLL_API char * Reader(); (i need to figure out this too)
extern "C" MTDLL_API int init();
extern "C" MTDLL_API int init_set(char*);
extern "C" MTDLL_API int init_base();
01.mandar 15-Nov-11 2:18am    
well when i checked in dependency walker
i dont know but some function are still exported as c++

E
C | extern "C" MYDLL_API char * Reader();
C | extern "C" MTDLL_API int init();
C++| extern "C" MTDLL_API int init_set(char*);
C++| extern "C" MTDLL_API int init_base();

if decorated option is checked
E
C | Reader;
C | init
C++| ??init_set@@YAPADD@Z
C++| ??init_base@@YAHXZ

i cant figure out why this function are still decorated when i used extern c


You need to use Marshaling[^].

C++ takes a string as the raw ASCII (for char *) data, followed by a single byte with the value of 0. Not sure how C# stores it's string, but I bet there is a length stored in there somewhere.

So, a very simple example:
MYDLL.cpp:
C++
#include <Windows.h>
#include <stdio.h>

//MUST have extern "C" if in C++, otherwise the name will be mangled

extern "C" __declspec(dllexport) int init_set(char *sz) {
	printf("%s\n", sz);
	return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  nReason, LPVOID lpReserved) {
	return TRUE;
}


and the C# file:
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices; //has the Marshal class

namespace CS_CLI
{

    class Program
    {
        [DllImport("MYDLL.dll")]
        public static extern int init_set(IntPtr s); //The type is a pointer (to characters) in C, so we need to say this, with IntPtr

        static void Main(string[] args)
        {
            String str = "I am a managed String"; //Some random string
            IntPtr ptrCString = (IntPtr)Marshal.StringToHGlobalAnsi(str); //Our actual marshal. This creates a copy of the string in unmanaged memory. This also converts the unicode string used in C# to ascii (char* is ASCII, wchar_t* is Unicode)
            init_set(ptrCString); //Call our function
            Marshal.FreeHGlobal(ptrCString); //Free the copy of the memory we made 2 lines above
        }
    }
}
 
Share this answer
 
Comments
01.mandar 15-Nov-11 1:56am    
i have tried the code above and some more possibilities
http://msdn.microsoft.com/en-us/magazine/cc164193.aspx#S2

but still have error "An unhandled exception of type 'System.EntryPointNotFoundException' occurred in usedll.exe
Additional information: Unable to find an entry point named 'init_set' in DLL 'MYDLL.dll'."

==================================================
Function Name : int __cdecl inti_set(char *)
Address : 0x10026708
Relative Address : 0x00026708
Ordinal : 1 (0x1)
Filename : MYDLL.dll
Full Path : D:\GSM\usedll\bin\Debug\MYDLL.dll
Type : Exported Function
==================================================

==================================================
Function Name : int __cdecl inti_base(void)
Address : 0x1002609b
Relative Address : 0x0002609b
Ordinal : 2 (0x2)
Filename : MYDLL.dll
Full Path : D:\GSM\usedll\bin\Debug\MYDLL.dll
Type : Exported Function
==================================================

==================================================
Function Name : Reader
Address : 0x10026307
Relative Address : 0x00026307
Ordinal : 3 (0x3)
Filename : MYDLL.dll
Full Path : D:\GSM\usedll\bin\Debug\MYDLL.dll
Type : Exported Function
==================================================

==================================================
Function Name : init
Address : 0x1002704a
Relative Address : 0x0002704a
Ordinal : 4 (0x4)
Filename : MYDLL.dll
Full Path : D:\GSM\usedll\bin\Debug\MYDLL.dll
Type : Exported Function
==================================================

#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif

extern "C" MYDLL_API char * Reader(); (i need to figure out this too)
extern "C" MTDLL_API int init();
extern "C" MTDLL_API int init_set(char*);
extern "C" MTDLL_API int init_base();
I have just created a simple DLL as follows, which creates the correct linkage, and my C# test program can invoke the methods:
1. Header file (zzdll.h)
C++
#pragma once

#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>

#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif

extern "C" MYDLL_API int __stdcall init_set(char*);
extern "C" MYDLL_API int __stdcall init_valid();


2. Implementation file (zzdll.cpp)
C++
#include "zzdll.h"


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}


MYDLL_API int __stdcall init_set(char*)
{
	return 1;
}

MYDLL_API int __stdcall init_valid()
{
	return 1;
}

The tag MYDLL_EXPORTS is defined to the compiler.

[edit]
Added __stdcall for correct function linkage.
[/edit]
 
Share this answer
 
v2
Comments
Andrew Brock 15-Nov-11 4:45am    
The main issue here is that C# uses managed Unicode strings, and C uses raw ASCII strings.
Richard MacCutchan 15-Nov-11 5:03am    
I just tested this, passing a simple C# string to the C++ function and it appeared to the C++ code as ASCII, which is, I think, the default marshalling for strings.
01.mandar 15-Nov-11 8:24am    
Perfect
even tried with
extern "C" TESTDLL_API char* __stdcall init_set1(char*);
and it worked too
a new project with above code worked fine thanks , i still don't know what i was missing.
is it that in dll code the last line should have newline in it
Richard MacCutchan 15-Nov-11 8:41am    
No idea why yours was wrong. I created my test from scratch so it could have been anything messing up your build; I shouldn't worry about it now you have a solution.

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900