欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

(適用于C++、C#)

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

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

子結(jié)構(gòu)體中的第一個成員偏移量應(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#的基本類型對應(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#工程中勾選啟動本地代碼調(diào)試如下入所示,這樣調(diào)試的時候才會進(jìn)入C++代碼。

在這里插入圖片描述

建議在VS的解決方案屬性中,將C#控制臺項(xiàng)目依賴C++的dll項(xiàng)目,如下入所示。這樣編譯C#項(xià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個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)體對齊方式一致
	{
		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)體對齊方式一致
{
    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)體對齊方式一致
	{
		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)體對齊方式一致
{
    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)體對齊方式一致
{
    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#中也會變
{
	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)體對齊方式一致
{
    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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • 在C# WPF下自定義滾動條ScrollViewer樣式的操作

    在C# WPF下自定義滾動條ScrollViewer樣式的操作

    這篇文章主要介紹了在C# WPF下自定義滾動條ScrollViewer樣式的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • 操作XML文檔遇到的XMLNS問題及解決方法 (C# 和 PHP)

    操作XML文檔遇到的XMLNS問題及解決方法 (C# 和 PHP)

    不管是用 PHP 還是 C#, 在操作 XML 的時候我們除了一個節(jié)點(diǎn)一個節(jié)點(diǎn)去取值之外, 還有一個非常方便的表達(dá)式, 就是 XPATH
    2011-05-05
  • Unity實(shí)現(xiàn)模型點(diǎn)擊事件的方法

    Unity實(shí)現(xiàn)模型點(diǎn)擊事件的方法

    這篇文章主要介紹了Unity實(shí)現(xiàn)模型點(diǎn)擊事件的方法,本文通過多種方法給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-05-05
  • C# 使用BitBlt進(jìn)行窗口抓圖的示例

    C# 使用BitBlt進(jìn)行窗口抓圖的示例

    這篇文章主要介紹了C# 使用BitBlt進(jìn)行窗口抓圖的示例,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下
    2021-01-01
  • C#讀取CSV文件的方法總結(jié)

    C#讀取CSV文件的方法總結(jié)

    CSV文件是一種簡單的文本文件格式,用于存儲表格數(shù)據(jù),在C#中,有多種方法可以用于讀取CSV文件,本文將介紹幾種常見的讀取CSV文件的方法,包括使用System.IO命名空間中的類、使用CsvHelper庫以及使用LINQ,需要的朋友可以參考下
    2024-05-05
  • C# .Net8 switch的用法小結(jié)

    C# .Net8 switch的用法小結(jié)

    在 .net 8中,switch 不需要再和傳統(tǒng)的寫法一樣了,會更加的方便,本文主要介紹了C# .Net8 switch的用法小結(jié),具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • C#獲取微信小程序的云數(shù)據(jù)庫中數(shù)據(jù)的示例代碼

    C#獲取微信小程序的云數(shù)據(jù)庫中數(shù)據(jù)的示例代碼

    本文主要介紹了C#獲取微信小程序的云數(shù)據(jù)庫中數(shù)據(jù)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Unity實(shí)現(xiàn)單機(jī)游戲每日簽到系統(tǒng)

    Unity實(shí)現(xiàn)單機(jī)游戲每日簽到系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)單機(jī)游戲每日簽到系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • C#使用CallContext緩存線程數(shù)據(jù)

    C#使用CallContext緩存線程數(shù)據(jù)

    這篇文章介紹了C#使用CallContext緩存線程數(shù)據(jù)的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • C#類型轉(zhuǎn)換之自定義隱式轉(zhuǎn)換和顯式轉(zhuǎn)換

    C#類型轉(zhuǎn)換之自定義隱式轉(zhuǎn)換和顯式轉(zhuǎn)換

    本文主要為大家介紹了一個新的類型轉(zhuǎn)換方法:通過自定義隱式轉(zhuǎn)換,把不一樣的數(shù)據(jù)類型反序列化為一樣的數(shù)據(jù)類型,需要的同學(xué)可以參考一下
    2022-03-03

最新評論