A series of problems encountered when C # calls C++dll encapsulation __c++

Source: Internet
Author: User
Tags server port

Recently help the bottom of the development of the same time with C # to encapsulate the DLL, that is, C # class to encapsulate the C++dll method, for users to use.

Before the use of similar applications, most of the problems are in the type conversion, but this application is endless, so here to sum up for their own future inspection, but also hope that we can help.

  

First, repeat some basic usage methods. The specific way is not repeated here, online a lot of. Like http://blog.csdn.net/sunboyljp/archive/2009/12/31/5110639.aspx.

Definition in the C + + header file:

Npd_api int np_init ();

Defining functions in C #

[DllImport ("Npd_api.dll")]

public static extern int Np_init ();

Basic type conversions See the following table (which I used):

Bstr--stringbuilder

Lpctstr--stringbuilder

Lpcwstr--intptr

Handle--intptr

Hwnd--intptr

Char *--string

int *--ref int

int &--ref int

void *--intptrs

unsigned char *--ref byte

Bool--bool

Dword--uint or int (I'm using uint, nothing's wrong)

My question came, the long lessons I learned:

1, pointers to do when the parameters in C # must use ref or out keyword, especially the structure of the pointer, to not report memory errors, even if not the error data is not correct. Oh

Sipclient_api void WINAPI Sccleanup (sipclient * PSIP);

[DllImport ("Sipclient.dll")]
public static extern void Sccleanup (ref sipclient PSIP);

One of the sipclient is a structural body.

2, when rewriting the structure, there is a point of type length or length of the array, the corresponding annotation, or can cause memory errors. Code

typedef struct {char sdvrip[]/* DVR IP address/char sdvripmask[];/* DVR IP address mask/DWORD Dwnetinter Face /* 10m/100m Adaptive, Index * * * WORD wdvrport; /* Port number */BYTE Bymacaddr[macaddr_len];    /* The physical address of the server * *}net_posa_ethernet; public struct Net_posa_ethernet {[MarshalAs (unmanagedtype.byvaltstr, SizeConst =)] public string Sdvrip;//DVR IP Address [MarshalAs (UnmanagedType.ByValTStr, SizeConst =)] public string sdvripmask; DVR IP address mask public uint dwnetinterface; Network interface 1-10mbase-t 2-10mbase-t full duplex 3-100mbase-tx 4-100m full duplex 5-10m/100m adaptive public uint Wdvrport; Port number [MarshalAs (UnmanagedType.ByValArray, SizeConst = 6)] public byte [] bymacaddr; [Macaddr_len]; PPPoE user name/server physical Address}

3, encountered such a problem, tossing a large half-day time--http://space.cnblogs.com/q/16616/.

//////////////////////////////////////////////////////////////////////////////////////////////////

Always feel that C # call C++dll this piece is very troublesome, but there is no way to use. Just start type conversion headache for a while, but also all resolved, today encountered this problem, is how to get through, I hope everyone to guide.

C + + prototype:

struct Sipclient {char * realm; void * LPVOID; char * FROM_IP; int from_port; char * TO_IP; int to_port; char * client_id ; char * SERVER_ID; Platform encoding int reg_count; Sipclient () {memset (this, 0, sizeof (sipclient));} ~ sipclient () {delete[] from_ip; delete[] Realm; delete[] client_id; Delete[] TO_IP; Delete[] server_id; } }; Sipclient_api sipclient * SCINIT (const char * reaml, const char * from_ip, int from_port, const char * to_ip, int to_port , const char * server_id, const char * user_id, const char * user_name, void * user_obj_param);

It's in C #.

public struct Sipclient {public string realm;//Authentication code public INTPTR LPVOID;//user parameter public string from_ip;//local IP public int from_port; Local port public string to_ip; SIP server IP public int to_port; SIP server Port public string client_id; The user's encoding public string server_id; The encoding public int reg_id of the SIP server; Reserved, temporarily not used} [DllImport ("Sipclient.dll")] public static extern sipclient Scinit (string Reaml, string from_ip, int fro M_port, string to_ip, int to_port, string server_id, String user_id, String user_name, IntPtr User_obj_param); function calls Private Const string user_id = "180400000090000000"; Private Const string server_id = "180400000099000000"; Sipclient_api. Scinit ("192.168.10.23", "192.168.10.32", 5092, "192.168.10.23", 5090, server_id, user_id, user_id, IntPtr.Zero);

When writing sipclient at the yellow mark, the Run-time function calls an exception:

Additional information: The type signature of the method is incompatible with the PInvoke.

To follow a practice on the web, change Sipclient to IntPtr, run or go wrong, but the exception is:

Additional information: Cannot find an entry point named "Scinit" in DLL "Sipclient.dll".

I can think of a way to use, or can not solve these problems, look forward to your answer.

/////////////////////////////////////////////////////////////////////////////////////////////////

Finally, the C + + has done a modification to solve, through the development of module definition (. def) file, unified development of the export function of the corresponding name.   Functions that return a value of a struct pointer can also be used with IntPtr. Code

Sipclient_api sipclient * SCINIT (const char * reaml, const char * from_ip, int from_port, const char * to_ip, int to_ Port, const char * server_id, const char * user_id, const char * user_name, void * user_obj_param); [DllImport ("Sipclient.dll")] public static extern IntPtr Scinit (string Reaml, string from_ip, int from_port, string t   o_ip, int to_port, string server_id, String user_id, String user_name, IntPtr User_obj_param); INTPTR client = IntPtr.Zero;
Client = Sipclient_api. Scinit (REALM, Client_ip, Client_port, Server_ip, Server_port, server_id, user_id, user_id, IntPtr.Zero);
if (client!= IntPtr.Zero)
Sipclient = (sipclient) marshal.ptrtostructure (client, typeof (Sipclient));
Else
MessageBox.Show ("Sipclient initialization failed.) ");

4, later also encountered a callback function caused by the crash problem, and delayed a large half-day time, work is still delayed will finally find solutions.

////////////////////////////////////////////

WINAPI See windef.h this header file
#define WINAPI __stdcall
By default, our function calls follow the __stdcall rule. Of course, there are rules such as __cdecl, __pascal and so on.
Using __stdcall or __cdecl or __pascal is not particularly necessary under pure Windows programming.
__stdcall:
1, the function of the call, function parameters of the stack way is the most right first into the stack.
2, at the same time __stdcall regulations, the caller is responsible for the stack recovery. Of course, the work is done by the application itself and does not need to be written by the creator. Assembly language is different (pop SP pop BP, etc.)
Digression: __pascal's calling rule is left to right, just as opposed to __stdcall.
3, c calling convention (that is, with the __CDECL keyword description) (the C default calling convention) in the order from right to left in the sequence of parameters into the stack, by the caller to the parameters pop-up stack. The memory stack for the transfer parameter is maintained by the caller (because of this, a function that implements the variable parameter vararg (such as printf) can only use that calling convention. In addition, there are differences in function name modification conventions. _CDECL is the default invocation method for C and C + + programs. Each function that calls it contains the code that empties the stack, so the resulting executable file size is larger than the call to the _stdcall function. The function takes the form of a right to left pressure stack. VC compiles the function with an underscore prefix in front of the function name.
Is the MFC default calling convention.
The stack is used during function calls. __stdcall and __cdecl are two different function calling conventions that define the order in which function parameters are placed in the stack, whether the call function or the called function pops up the parameter stack, and the method that produces the function decorated name. For more information about the two calling conventions, the reader can refer to MSDN. For functions with variable number of parameters, such as printf, the __cdecl calling convention is used, and WIN32 API functions follow the __stdcall calling convention. In the VC + + development Environment, the default compilation option is __cdecl, and for those functions that require __stdcall calling conventions, you must explicitly add __stdcall to the declaration. In a Windows program, the callback function must follow the __stdcall calling convention, so we use callback when declaring the callback function. The reason for using callback instead of __stdcall is to tell us that this is a callback function. Note that under Windows 98 and Windows 2000, when declaring a window procedure function, there is no error even if you do not use callback, but under Windows NT4.0, an error

////////////////////////////////////////////

At first, colleagues analyzed the cause of the crash, are the trouble of recycling, see Http://www.hudong.com/wiki/WINAPI, try to use __stdcall, but still did not solve the problem

Later practice proved that the procedure is very rigorous, the slightest error can not be led to errors, ideas or __stdcall, but less changed things, there are two places need to change, in order to ensure that no error.

Reference http://hi.baidu.com/tease/blog/item/1fe7213802780f22b9998f5a.html.

The key is these two words

typedef void (_stdcall *cicicallback) (bool started, void* Client,char *message);
Modify the export function to:
extern "C" _declspec (dllexport) bool _stdcall Test (char* fileName, Cicicallback callback)

At the beginning of the time only to modify the definition that, but forgot the export of the changes, almost gave up the idea of the solution, but fortunately, the so-called persistence is victory.

  
5, later packaged to get users there, but always hint that the C + + those DLLs are not found.

On the Internet, preliminary positioning is caused by the development environment, and environmental deployment has a relationship. Our development environment is VS2008, and the customer uses the VS2010, through several attempts, the question finally.

The first consideration is the lack of some C + + prerequisite runtime libraries, which are interdependent, causing the DLL to be found. See dependency Walker to see if it's true that something is missing from the client's son.

But blocked, the missing items are copied to the executable directory, and the problem remains unresolved. But still stick to the road

The problem persists if you attempt to install Vcredist_x86.exe to troubleshoot the possibility of some runtime libraries being missing.

Then I thought about the search problem, and I saw that it had something to do with the Releas\debug version of the DLL, and all of them tried to suggest that colleagues change their c++dll to release.

Because the project is many people together to do, compiling release version also took a lot of time, but at least the problem solved.

Summary: Install Vcredist_x86.exe directly, all DLLs must use release version. If you use the debug version, you must ensure that the DLL in the executable directory is complete and integral.

Online detailed explanation also a lot of, feel this summed up very good http://hi.baidu.com/fairysky/blog/item/e7a8366dbaa735f3431694c8.html.

To do the program is afraid of problems, there are problems do not know why, know the reason for the solution to find solutions.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.