最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#調(diào)用C++的實(shí)現(xiàn)步驟

 更新時(shí)間:2024年11月29日 10:34:18   作者:qq_27663383  
本文主要介紹了C#調(diào)用C++的基本規(guī)則和方法,包括內(nèi)存對(duì)齊、調(diào)用約定、基本數(shù)據(jù)類型的傳遞、結(jié)構(gòu)體的傳遞以及數(shù)組的傳遞等,感興趣的可以了解一下

1、內(nèi)存對(duì)齊的規(guī)則

(適用于C++、C#)

首先需要了解C++、C#的內(nèi)存對(duì)齊的規(guī)則:

結(jié)構(gòu)體的數(shù)據(jù)成員,第一個(gè)成員的偏移量為0,后面的每個(gè)數(shù)據(jù)成員存儲(chǔ)的起始位置要從自己大小的整數(shù)倍開始。

子結(jié)構(gòu)體中的第一個(gè)成員偏移量應(yīng)當(dāng)是子結(jié)構(gòu)體中最大成員的整數(shù)倍。

結(jié)構(gòu)體總大小必須是其內(nèi)部最大成員的整數(shù)倍。

以下為C#示例代碼:

internal class Program
{
    struct Info
    {
        double dd;//32-40
        bool bo;//40-48
    }
    struct MyStruct
    {
        char c;//0-1
        decimal d;//8-16
        int a;//16-20
        double b;//24-32
        Info info;//32-
    }
    static unsafe void Main(string[] args)
    {
        Console.WriteLine(sizeof(MyStruct));//輸出結(jié)果:48
    }
}

2、調(diào)用約定

  • _cdecl稱之為c調(diào)用約定,參數(shù)從右至左的方式入棧,函數(shù)本身不清理?xiàng)?,此工作由調(diào)用者負(fù)責(zé),所以允許可變參數(shù)函數(shù)存在。我們自己編寫的程序一般為_cdecl

  • _stdcall稱之為標(biāo)準(zhǔn)調(diào)用約定,參數(shù)從右至左的方式入棧,函數(shù)本身清理?xiàng)?,所以不允許可變參數(shù)函數(shù)存在。windowsAPI一般為_stdcall

3、C#傳遞基本數(shù)據(jù)類型到C++

C++與C#的基本類型對(duì)應(yīng)關(guān)系如下表所示,數(shù)據(jù)通過值傳遞

C++基本類型C#基本類型
intint
charsbyte
shortshort
floatfloat
doubledouble
long longlong
boolbool
char*string(傳值,需CharSet = CharSet.Ansi)
int*,double*ref int,ref double
int&,double&ref int,ref double

**不要將C#中托管堆上的數(shù)據(jù),按照傳引用的方式傳遞到C++中 **

C++ 代碼

//native.h文件
extern "C"
{
	__declspec(dllexport) void __cdecl TestBasicData(bool d1,char d2,short d3,
		int d4,long long d5,float d6,double d8);
}

//native.cpp文件
#include "native.h"
void __cdecl TestBasicData(bool d1, char d2, short d3, int d4, long long d5, float d6, double d8)
{
	return;//在此處添加斷點(diǎn),觀察在C#中的數(shù)據(jù)傳遞到了C++代碼中
}

C#代碼

[DllImport("NativeDll", CallingConvention = CallingConvention.Cdecl)]
public static extern int TestBasicData(bool d1, sbyte d2, short d3,
                                       int d4, long d5, float d6, double d8);
static void Main(string[] args)
{
    TestBasicData(true, 64, 128, 123456, 123456789, 12.45f, 3.142592);
}

注意:使用VS調(diào)試過程中,需要在C#工程中勾選啟動(dòng)本地代碼調(diào)試如下入所示,這樣調(diào)試的時(shí)候才會(huì)進(jìn)入C++代碼。

在這里插入圖片描述

建議在VS的解決方案屬性中,將C#控制臺(tái)項(xiàng)目依賴C++的dll項(xiàng)目,如下入所示。這樣編譯C#項(xiàng)目會(huì)自動(dòng)編譯C++項(xiàng)目。

在這里插入圖片描述

4、C#傳遞基本數(shù)據(jù)類型的數(shù)組到C++

**不要將C#中托管堆上的數(shù)據(jù),按照傳引用的方式傳遞到C++中 **

以下以傳遞int*為例

C++代碼如下,生成NativeDll.dll文件

//native.h文件
#pragma once
extern "C"
{
	__declspec(dllexport) int __cdecl TestAddDoubles(int* d, int length);
}

//native.cpp文件
#include "native.h"
int __cdecl TestAddDoubles(int* d, int length)
{
	int re = 0;
	for (size_t i = 0; i < length; i++)
	{
		re += d[i];
		d[i] = 99;//改變d地址內(nèi)的數(shù)據(jù),在C#代碼中也可以看到dpoint地址內(nèi)的數(shù)據(jù)被改為99
	}
	return re;
}

C#代碼如下

[DllImport("NativeDll", CallingConvention = CallingConvention.Cdecl)]
public static extern int TestAddDoubles(IntPtr d, int length);
static void Main(string[] args)
{
    IntPtr dpoint = Marshal.AllocHGlobal(sizeof(int)*4);//在非托管內(nèi)存中創(chuàng)建4個(gè)int大小內(nèi)存的指針
    unsafe
    {
        int* ptr = (int*)dpoint.ToPointer();
        ptr[0] = 1;
        ptr[1] = 3;
        ptr[2] = 5;
        ptr[3] = 7;
    }
    var re = TestAddDoubles(dpoint, 4);
    Console.WriteLine(re);//輸出結(jié)果為16
    Marshal.FreeHGlobal(dpoint);//非托管內(nèi)存需要在C#代碼中釋放
    Console.ReadLine();
}

5、C#傳遞基本類型組成的結(jié)構(gòu)體給C++

5.1 按值傳遞基本類型組成的結(jié)構(gòu)體

**不要將C#中托管堆上的數(shù)據(jù),按照傳引用的方式傳遞到C++中 **

C++代碼如下

//native.h文件
extern "C"
{
	struct Shape//注意:一定要與C#中的結(jié)構(gòu)體對(duì)齊方式一致
	{
		int x;
		int y;
		int z;
		double area;
		double volume;
	};
	__declspec(dllexport) int __cdecl TestStructor(Shape p);
}

//native.cpp文件
#include"native.h"
int __cdecl TestStructor(Shape p)
{
	return sizeof(p);
}

C#代碼如下

struct Shape//注意:一定要與C++中的結(jié)構(gòu)體對(duì)齊方式一致
{
    public int x;
    public int y;
    public int z;
    public double area;
    public double volume;
}


[DllImport("NativeDll", CallingConvention = CallingConvention.Cdecl)]
public static extern int TestStructor(Shape shape);
static void Main(string[] args)
{
    Shape shape = new Shape() { x = 10, y = 20, z = 30, area = 123.45, volume = 3456.98 };
    var len = TestStructor(shape);//傳值得方式將結(jié)構(gòu)體傳給C++
    Console.WriteLine(len);
}

5.2 按引用傳遞基本類型組成的結(jié)構(gòu)體給C++結(jié)構(gòu)體指針

**不要將C#中托管堆上的數(shù)據(jù),按照傳引用的方式傳遞到C++中 **

C++代碼如下

//native.h文件
extern "C"
{
	struct Shape//注意:一定要與C#中的結(jié)構(gòu)體對(duì)齊方式一致
	{
		int x;
		int y;
		int z;
		double area;
		double volume;
	};
	__declspec(dllexport) int __cdecl TestStructorPointer(Shape* p);
}

//native.cpp文件
#include"native.h"
int __cdecl TestStructorPointer(Shape* p)
{
	int r = sizeof(*p);
	p->x = 100;
	p->y = 100;
	p->z = 100;
	p->area = 10.1;
	p->volume = 10.1;
	return r;
}

C#代碼如下

struct Shape//注意:一定要與C++中的結(jié)構(gòu)體對(duì)齊方式一致
{
    public int x;
    public int y;
    public int z;
    public double area;
    public double volume;
}


[DllImport("NativeDll", CallingConvention = CallingConvention.Cdecl)]
public static extern int TestStructorPointer(ref Shape shape);
static void Main(string[] args)
{
    Shape shape = new Shape() { x = 10, y = 20, z = 30, area = 123.45, volume = 3456.98 };
    var len = TestStructorPointer(ref shape);//ref方式將結(jié)構(gòu)體傳給C++,通過斷點(diǎn)調(diào)試,查看C#中的shape也更改了
    Console.WriteLine(len);
}

6、C#傳遞元素有數(shù)組的結(jié)構(gòu)體

**不要將C#中托管堆上的數(shù)據(jù),按照傳引用的方式傳遞到C++中 **

結(jié)構(gòu)體是按值進(jìn)行傳遞的。

C++代碼如下

//native.h文件
#pragma once
extern "C"
{
	struct Student
	{
		char name[50];
		int age;
		double score;
	};
	__declspec(dllexport) int __cdecl TestStudentStructor(Student s);
}

//native.cpp文件
#include "native.h"
int __cdecl TestStudentStructor(Student s)
{
	int len = sizeof(s);
	return len;
}

C#中的結(jié)構(gòu)體映射到C++內(nèi)存中,要求結(jié)構(gòu)體只能包含非托管類型

C#代碼如下

unsafe struct Student//注意:一定要與C++中的結(jié)構(gòu)體對(duì)齊方式一致
{
    public fixed byte name[50];
    public int age;
    public double score;
}

[DllImport("NativeDll", CallingConvention = CallingConvention.Cdecl)]
public static extern int TestStudentStructor(Student s);
static unsafe void Main(string[] args)
{
    Student s = new Student();
    s.age = 12;
    s.score = 123.4;
    var name = Encoding.GetEncoding("GB2312").GetBytes("abcd\0");//C++的字符串編碼為GB2312,結(jié)尾添加\0
    Marshal.Copy(name, 0,new IntPtr(s.name),name.Length);
    var len = TestStudentStructor(s);
    Console.WriteLine(len);
}

7、C#傳遞元素有數(shù)組的結(jié)構(gòu)體指針

** 不要將C#中托管堆上的數(shù)據(jù),按照傳引用的方式傳遞到C++中 **

C++代碼如下

//native.h文件
#pragma once
extern "C"
{
	struct Student
	{
		char name[50];//結(jié)構(gòu)體中含有char數(shù)組
		int age;
		double score;
	};
	__declspec(dllexport) int __cdecl TestStudentStructorPointer(Student* s);
}

//native.cpp文件
#include "native.h"
int __cdecl TestStudentStructorPointer(Student* s)//C++中改變s,C#中也會(huì)變
{
	int len = sizeof(*s);
	s->age = 1000;
	s->score = 1000.0;
	for (size_t i = 0; i < sizeof(s->name); i++)
	{
		s->name[i] = 123;
	}
	return len;
}

C#中的結(jié)構(gòu)體映射到C++內(nèi)存中,要求結(jié)構(gòu)體只能包含非托管類型

C#代碼如下

unsafe struct Student//注意:一定要與C++中的結(jié)構(gòu)體對(duì)齊方式一致
{
    public fixed byte name[50];
    public int age;
    public double score;
}

[DllImport("NativeDll", CallingConvention = CallingConvention.Cdecl)]
public static extern int TestStudentStructorPointer(ref Student s);//使用ref
static  void Main(string[] args)
{
    Student s = new Student();
    s.age = 12;
    s.score = 123.4;
    var name = Encoding.GetEncoding("GB2312").GetBytes("abcd\0");//結(jié)尾添加\0
    unsafe
    {
        Marshal.Copy(name, 0, new IntPtr(s.name), name.Length);
    }
    var len = TestStudentStructorPointer(ref s);//ref方式將結(jié)構(gòu)體傳給C++,通過斷點(diǎn)查看C#中的s也更改了
    Console.WriteLine(len);
}

到此這篇關(guān)于C#調(diào)用C++的實(shí)現(xiàn)步驟的文章就介紹到這了,更多相關(guān)C#調(diào)用C++內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • 事務(wù)在c#中的使用

    事務(wù)在c#中的使用

    這篇文章介紹了事務(wù)在c#中的使用,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • C#通過html調(diào)用WinForm的方法

    C#通過html調(diào)用WinForm的方法

    這篇文章主要介紹了C#通過html調(diào)用WinForm的方法,涉及html頁(yè)面中使用JavaScript訪問C#的相關(guān)技巧,需要的朋友可以參考下
    2016-04-04
  • 一文詳解C#中String字符串的常見操作與日期格式化方法

    一文詳解C#中String字符串的常見操作與日期格式化方法

    這篇文章主要為大家詳細(xì)介紹了C#中字符串的常用操作與日期格式化方法,主要包括字符串的4種創(chuàng)建方式,String類的常用屬性和方法等內(nèi)容,希望對(duì)大家有所幫助
    2026-02-02
  • C#實(shí)現(xiàn)塊狀鏈表的項(xiàng)目實(shí)踐

    C#實(shí)現(xiàn)塊狀鏈表的項(xiàng)目實(shí)踐

    這篇文章主要介紹了C#實(shí)現(xiàn)塊狀鏈表的項(xiàng)目實(shí)踐,通過定義塊和鏈表類,利用塊內(nèi)元素引用實(shí)現(xiàn)塊與塊之間的鏈接關(guān)系,從而實(shí)現(xiàn)對(duì)塊狀鏈表的遍歷、插入和刪除等操作,感興趣的可以了解一下
    2023-11-11
  • C#中OpenCVSharp實(shí)現(xiàn)輪廓檢測(cè)

    C#中OpenCVSharp實(shí)現(xiàn)輪廓檢測(cè)

    這篇文章主要介紹了C#中OpenCVSharp實(shí)現(xiàn)輪廓檢測(cè),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • C#自定義組件實(shí)現(xiàn)表格的多層表頭功能

    C#自定義組件實(shí)現(xiàn)表格的多層表頭功能

    這篇文章主要為大家詳細(xì)介紹了如何使用C#自定義組件實(shí)現(xiàn)表格的多層表頭功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-12-12
  • C#控制臺(tái)帶參數(shù)程序源碼編寫實(shí)例講解

    C#控制臺(tái)帶參數(shù)程序源碼編寫實(shí)例講解

    像ipconfig /all 這樣的CMD命令想必大家都知道,但是很多童鞋可能不知道怎么寫這樣的控制臺(tái)帶參數(shù)的程序,需要的朋友可以了解下
    2012-12-12
  • C#編寫發(fā)送郵件組件

    C#編寫發(fā)送郵件組件

    本文給大家分享的是使用C#編寫的發(fā)送郵件的組件,非常的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。
    2015-06-06
  • C#純技術(shù)之Class寫入Json

    C#純技術(shù)之Class寫入Json

    這篇文章主要介紹了C#純技術(shù)之Class寫入Json問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • WPF實(shí)現(xiàn)播放RTSP視頻流

    WPF實(shí)現(xiàn)播放RTSP視頻流

    這篇文章主要為大家詳細(xì)介紹了WPF實(shí)現(xiàn)播放RTSP視頻流的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-01-01

最新評(píng)論

东丽区| 沈阳市| 科技| 峡江县| 武义县| 浦县| 太仆寺旗| 乐山市| 榕江县| 远安县| 白朗县| 广平县| 家居| 习水县| 万州区| 兴业县| 淳安县| 红桥区| 连平县| 黄陵县| 视频| 增城市| 常州市| 濮阳县| 安徽省| 景宁| 定兴县| 灵宝市| 临沂市| 翁源县| 泰和县| 泊头市| 葵青区| 武功县| 习水县| 平阴县| 大渡口区| 从江县| 邻水| 盐津县| 高邑县|