您好,登錄后才能下訂單哦!
這篇文章主要介紹“ c++互調的使用方法”,在日常操作中,相信很多人在 c++互調的使用方法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答” c++互調的使用方法”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
#if !defined(__CCALLDLL2__) #define __CCALLDLL2__ #ifdef C_API_EXPORTS #define C_API_TEST extern __declspec(dllexport) #else #define C_API_TEST extern __declspec(dllimport) #endif // C_API_EXPORTS #ifdef __cplusplus extern "C" { #endif //#define extern "C" __declspec(dllimport) struct user { int id; int age; }; struct structpointer { int id; int* ptrid; }; typedef void(*cbfun1)(int x, int y); typedef int(*cbfun2)(int x, int y); struct alignteststruct { int v1; char v2; char v3; int v4; }; struct alignteststruct2 { int v1; char v2; char* v3; int v4; }; struct alignteststruct3 { int v1; char v2; char* v3[3]; int v4; }; C_API_TEST int say(int u); C_API_TEST int saystruct(user u); C_API_TEST int retstruct(user* u, int x, int y); C_API_TEST user* retstructptr(user* u, int x, int y); C_API_TEST void setstructs(user u[], int len, int x, int y); C_API_TEST void processstructpointer(structpointer *sp); C_API_TEST void processstructpointer2(structpointer *sp, int len); C_API_TEST void cbfundemo(user* u, int x, int y, cbfun1 cb); C_API_TEST int cbfundemo2(user* u, int x, int y, cbfun2 cb); C_API_TEST void dispalign(alignteststruct ats); C_API_TEST void dispalign2(alignteststruct2 ats); C_API_TEST void dispalign3(alignteststruct3 ats); C_API_TEST void dispalign4(alignteststruct3 ats, int v3len); C_API_TEST void xxxByReference(char* c1, short* s1, int* i1, long* l1, float* f1, double* d1); C_API_TEST char* strtocharptr(char* arg); C_API_TEST void deletepr(); C_API_TEST int globalvar; //public Pointer getGlobalVariableAddress(java.lang.String symbolName) C_API_TEST char * test1(); C_API_TEST char * test2(); #ifdef __cplusplus } #endif #endif
// ccalldll2.cpp : 定義 DLL 應用程序的導出函數。 // #include "stdafx.h" #include <iostream> //#using "cSharpDLLforJNA.dll" using namespace System; using namespace cSharpDLLforJNA; using namespace std; //#pragma data_seg("MyData") //沒效果 int globalvar=58; //public Pointer getGlobalVariableAddress(java.lang.String symbolName) //#pragma data_seg() //https://www.cnblogs.com/luzhiyuan/p/3947576.html 中提到extern int g_nTest;和extern int _declspec(dllimport) g_nTest; //如果不用_declspec(dllimport)則代表的是地址,如果用到了則代表的是真實的變量 如果這樣的話,那可不可以用于hacker int say(int u) { /*gcnew User();*/ Main ^dllmain = gcnew Main(); user user; user.age = 20; user.id = 1; int r = dllmain->say(u); return r; } int saystruct(user u) { int r = u.id + u.age; return r; } int retstruct(user* u,int x,int y) { //直接在u上處理然后返回這個u,那么在java中原來的參數user與返回的user應該id/age都相同了,做實驗看看 u->id += 10 + x; u->age += 10 + y; return 0; } user* retstructptr(user* u, int x, int y) { //直接在u上處理然后返回這個u,那么在java中原來的參數user與返回的user應該id/age都相同了,做實驗看看 u->id += 20 + x; u->age += 20 + y; cout << "cpp_u->id=" << u->id << " u->age=" << u->age << endl; return u; } void setstructs(user u[], int len,int x, int y) { //int len = sizeof(u) / (2 * sizeof(int)); //不正確的做法,實驗發現傳入3個(????)打印顯示為1???? cout << "cpp_len=" << len << endl; for (int i = 0; i < len; i++) { u[i].id = x+i; u[i].age = y+i; cout << i<<":id=" << u[i].id << " age=" << u[i].age << endl; } } void processstructpointer(structpointer *sp) { if (sp == NULL) return; int* p; p = sp->ptrid; /*for (int i = 0; i < len; i++) {*/ //p = (sp + i)->ptrid; while (true) { if (*p != 0) { cout << *p << endl; *p += 1; p += 1; } else { break; } } //} } void processstructpointer2(structpointer *sp,int len) { if (sp == NULL) return; int* p; //p = sp->ptrid; for (int i = 0; i < len; i++) { p = (sp + i)->ptrid; cout << ">>>>>>>>>>>>" << endl; while (true) { if (*p != 0) { cout << *p << endl; *p += 1; p += 1; } else { break; } } } } void cbfundemo(user* u, int x, int y, cbfun1 cb) { u->id += x; u->age += y; cb(u->id, u->age); } int cbfundemo2(user* u, int x, int y, cbfun2 cb) { u->id += x; u->age += y; return cb(u->id, u->age); } void dispalign(alignteststruct ats) { cout << "dispalign=>"<<ats.v1 << ":" << ats.v2 << ":" << ats.v3 << ":" << ats.v4 << endl; } void dispalign2(alignteststruct2 ats) { cout << "dispalign=>" << ats.v1 << ":" << ats.v2 << ":" << ats.v3 << ":" << ats.v4 << endl; } void dispalign3(alignteststruct3 ats) { char (*p)[3] = (char (*)[3])ats.v3; //常量下標,如果是變量下標則ERROR //char *pp[3] = (char (*)[3])ats.v3; int line = sizeof(ats.v3) / sizeof(ats.v3[0]); cout << "line=" << line << endl; cout << "dispalign3==>" << ats.v1 << ":" << ats.v2 << ":" << ats.v3 << ":" << ats.v4 << endl; } void dispalign4(alignteststruct3 ats, int v3len) { //char(*p)[len] = (char(*)[len])ats.v3; //char *p[] = new char } void xxxByReference(char* c1, short* s1, int* i1, long* l1, float* f1, double* d1) { cout << "xxxByReference" << *c1 << ":" << *s1 << ":" << *i1 << ":" << *l1 << ":" << *f1 << ":" << *d1 << endl; *c1 += 1; *s1 += 1; *i1 += 1; *l1 += 1; *f1 += 1; *d1 += 1; globalvar += 1; } char* pr; char* strtocharptr(char* arg) { cout << "strtocharptr==>" << arg << endl; arg[1] += 1; cout << "strtocharptr2==>" << arg << endl; pr = (char*)malloc(1000000); memset(pr, 0, 1000000); int len = strlen(arg); memcpy(pr, arg, len); pr[len] = 'o'; pr[len + 1] = 'k'; return pr; } void deletepr() { if (pr != NULL) free(pr); pr = NULL; } char* pt; char * test1(){ pt = (char*)malloc(200000000); char buf[100] = "hello你world"; memcpy(pt, buf, 100); return pt; } char * test2(){ if (pt != NULL) { free(pt); cout << "free(pt)" << endl; } else cout << "no free" << endl; char* p = "helloworld你好,delete pt:"; cout << sizeof(p) << ":"<<sizeof("helloworld你好,delete pt:") <<endl; //8:26 return "helloworld你好,delete pt:"; } // dllmain.cpp : 定義 DLL 應用程序的入口點。 #include "stdafx.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; }
using System; using System.Collections.Generic; //using System.Linq; using System.Text; //using System.Threading.Tasks; namespace cSharpDLLforJNA { public class Main { //public struct user //{ // public int id; // //public string name; // public int age; //} //public void sayuser(user user) //{ // //Console.WriteLine(user.name + ":id=" + user.id + " age=" + user.age); // Console.WriteLine( "id=" + user.id + " age=" + user.age); //} public int say(int i) { Console.WriteLine("i=" + i); return i + 1; } } }
主c#程序的按鈕點擊事件及相關代碼:
[DllImport("ccalldll2.dll", EntryPoint = "retstruct",CallingConvention=CallingConvention.Cdecl)] public static extern int retstruct(IntPtr ptrUser, int x, int y); //在引用中只引用了ccalldll2,而ccalldll2又用到了cSharpDLLforJNA,這樣有問題嗎 //[DllImport("cSharpDLLforJNA.dll", EntryPoint = "say", CallingConvention = CallingConvention.Cdecl)] //public static extern int saybak(int i); //在引用中只引用了ccalldll2,而ccalldll2又用到了cSharpDLLforJNA,這樣有問題嗎 [StructLayout(LayoutKind.Sequential)] struct user { public int id; public int age; }; [DllImport("ccalldll2.dll", EntryPoint = "say", CallingConvention = CallingConvention.Cdecl)] public static extern int say1(int u); private void btnInptr_Click(object sender, EventArgs e) { user u = new user(); u.id = 5; u.age = 7; //先要通過Marshal來分配內存空間,根據user的大小進行分配非托管空間大小 int size = Marshal.SizeOf(u);//對于值類型,可以Sizeof(變量),對于引用類型則Sizeof(typeof(TYPE)) IntPtr ptruser = Marshal.AllocHGlobal(size);//分配內存 //將u的值copy到ptruser空間 Marshal.StructureToPtr(u, ptruser, false); int res = retstruct(ptruser, 5, 5);//調用DLL中函數 retstruct中將對ptruser指針所指的user中的id和age處理 user u2 = (user)Marshal.PtrToStructure(ptruser, typeof(user));//將處理之后的ptruser再轉換為user Console.WriteLine(u2.id + ":" + u2.age); Console.WriteLine(res+":"+u.id+":"+u.age); Marshal.FreeHGlobal(ptruser); Console.WriteLine(new Main().say(2)); Console.WriteLine("say=" + say1(3)); }
顯示如下:
20:22
0:5:7
i=2
3
i=3
say=4
其實就是cSharpDLLforJNA是c#做的dll,ccalldll2是c++,并且在其中調用了cSharpDLLforJNA.dll中函數,然后主程序中直接調用了SharpDLLforJNA中的函數(通過引用導入dll,代碼中用using cSharpDLLforJNA即可),主程序中還調用了ccalldll2.dll中的say函數,這個say還調用了SharpDLLforJNA中的函數。
到此,關于“ c++互調的使用方法”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。