千家信息网

c++互调的使用方法

发表于:2024-11-16 作者:千家信息网编辑
千家信息网最后更新 2024年11月16日,这篇文章主要介绍" c++互调的使用方法",在日常操作中,相信很多人在 c++互调的使用方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答" c++互调的使用方法"的疑惑
千家信息网最后更新 2024年11月16日c++互调的使用方法

这篇文章主要介绍" 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 //#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)则代表的是地址,如果用到了则代表的是真实的变量 如果这样的话,那可不可以用于hackerint 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 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) << ":"<
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++互调的使用方法"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

0