Skip to content

Commit 97f133a

Browse files
committed
Fix adjacent cpp code blocks, part 3 of N
1 parent b93fe03 commit 97f133a

10 files changed

+137
-104
lines changed

docs/dotnet/how-to-marshal-embedded-pointers-using-pinvoke.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
---
2-
description: "Learn more about: How to: Marshal Embedded Pointers Using PInvoke"
3-
title: "How to: Marshal Embedded Pointers Using PInvoke"
2+
description: "Learn more about: How to: Marshal embedded pointers using P/Invoke"
3+
title: "How to: Marshal embedded pointers using P/Invoke"
44
ms.custom: "get-started-article"
5-
ms.date: "11/04/2016"
5+
ms.date: 06/29/2022
66
helpviewer_keywords: ["embedded pointers [C++]", "interop [C++], embedded pointers", "platform invoke [C++], embedded pointers", "marshaling [C++], embedded pointers", "data marshaling [C++], embedded pointers"]
77
ms.assetid: f12c1b9a-4f82-45f8-83c8-3fc9321dbb98
88
---
9-
# How to: Marshal Embedded Pointers Using PInvoke
9+
# How to: Marshal embedded pointers using P/Invoke
1010

11-
Functions that are implemented in unmanaged DLLs can be called from managed code using Platform Invoke (P/Invoke) functionality. If the source code for the DLL is not available, P/Invoke is the only option for interoperating. However, unlike other .NET languages, Visual C++ provides an alternative to P/Invoke. For more information, see [Using C++ Interop (Implicit PInvoke)](../dotnet/using-cpp-interop-implicit-pinvoke.md) and [How to: Marshal Embedded Pointers Using C++ Interop](../dotnet/how-to-marshal-embedded-pointers-using-cpp-interop.md).
11+
Functions that are implemented in unmanaged DLLs can be called from managed code using Platform Invoke (P/Invoke) functionality. If the source code for the DLL isn't available, P/Invoke is the only option for interoperating. However, unlike other .NET languages, Visual C++ provides an alternative to P/Invoke. For more information, see [Using C++ Interop (Implicit P/Invoke)](../dotnet/using-cpp-interop-implicit-pinvoke.md) and [How to: Marshal embedded pointers using C++ Interop](../dotnet/how-to-marshal-embedded-pointers-using-cpp-interop.md).
1212

1313
## Example
1414

1515
Passing structures to native code requires that a managed structure that is equivalent in terms of data layout to the native structure is created. However, structures that contain pointers require special handling. For each embedded pointer in the native structure, the managed version of the structure should contain an instance of the <xref:System.IntPtr> type. Also, memory for these instances must be explicitly allocated, initialized, and released using the <xref:System.Runtime.InteropServices.Marshal.AllocCoTaskMem%2A>, <xref:System.Runtime.InteropServices.Marshal.StructureToPtr%2A>, and <xref:System.Runtime.InteropServices.Marshal.FreeCoTaskMem%2A> methods.
1616

17-
The following code consists of an unmanaged and a managed module. The unmanaged module is a DLL that defines a function that accepts a structure called ListString that contains a pointer, and a function called TakesListStruct. The managed module is a command-line application that imports the TakesListStruct function and defines a structure called MListStruct that is equivalent to the native ListStruct except that the double* is represented with an <xref:System.IntPtr> instance. Before calling TakesListStruct, the main function allocates and initializes the memory that this field references.
17+
The following code consists of an unmanaged and a managed module. The unmanaged module is a DLL that defines a function that accepts a structure called `ListString` that contains a pointer, and a function called `TakesListStruct`.
1818

1919
```cpp
2020
// TraditionalDll6.cpp
@@ -46,6 +46,8 @@ void TakesListStruct(ListStruct list) {
4646
}
4747
```
4848
49+
The managed module is a command-line application that imports the `TakesListStruct` function and defines a structure called `MListStruct` that is equivalent to the native `ListStruct` except that the `double*` is represented with an <xref:System.IntPtr> instance. Before it calls `TakesListStruct`, the `main` function allocates and initializes the memory that this field references.
50+
4951
```cpp
5052
// EmbeddedPointerMarshalling.cpp
5153
// compile with: /clr
@@ -88,8 +90,8 @@ int main() {
8890
}
8991
```
9092

91-
Note that no portion of the DLL is exposed to the managed code using the traditional #include directive. In fact, the DLL is accessed at run time only, so problems with functions imported with <xref:System.Runtime.InteropServices.DllImportAttribute> will not be detected at compile time.
93+
No portion of the DLL is exposed to the managed code using the traditional `#include` directive. In fact, the DLL is accessed at runtime only, so problems in functions imported by using <xref:System.Runtime.InteropServices.DllImportAttribute> can't be detected at compile time.
9294

9395
## See also
9496

95-
[Using Explicit PInvoke in C++ (DllImport Attribute)](../dotnet/using-explicit-pinvoke-in-cpp-dllimport-attribute.md)
97+
[Using explicit P/Invoke in C++ (`DllImport` attribute)](../dotnet/using-explicit-pinvoke-in-cpp-dllimport-attribute.md)

docs/dotnet/how-to-marshal-function-pointers-using-pinvoke.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,24 @@
11
---
2-
description: "Learn more about: How to: Marshal Function Pointers Using PInvoke"
3-
title: "How to: Marshal Function Pointers Using PInvoke"
2+
description: "Learn more about: How to: Marshal function pointers using P/Invoke"
3+
title: "How to: Marshal function pointers using P/Invoke"
44
ms.custom: "get-started-article"
5-
ms.date: "11/04/2016"
5+
ms.date: 06/29/2022
66
helpviewer_keywords: ["data marshaling [C++], callbacks and delegates", "interop [C++], callbacks and delegates", "platform invoke [C++], callbacks and delegates", "marshaling [C++], callbacks and delegates"]
77
ms.assetid: dcf396fd-a91d-49c0-ab0b-1ea160668a89
88
---
9-
# How to: Marshal Function Pointers Using PInvoke
9+
# How to: Marshal function pointers using P/Invoke
1010

11-
This topic explains how managed delegates can be used in place of function pointers when interoperating with unmanaged functions using .NET Framework P/Invoke features. However, Visual C++ programmers are encouraged to use the C++ Interop features instead (when possible) because P/Invoke provides little compile-time error reporting, is not type-safe, and can be tedious to implement. If the unmanaged API is packaged as a DLL and the source code is not available, P/Invoke is the only option. Otherwise, see the following topics:
11+
Managed delegates can be used in place of function pointers when interoperating with unmanaged functions by using .NET Framework P/Invoke features. However, we encourage you to use the C++ Interop features instead, when possible. P/Invoke provides little compile-time error reporting, isn't type-safe, and can be tedious to implement. If the unmanaged API is packaged as a DLL and the source code isn't available, P/Invoke is the only option. Otherwise, see these articles:
1212

13-
- [Using C++ Interop (Implicit PInvoke)](../dotnet/using-cpp-interop-implicit-pinvoke.md)
13+
- [Using C++ Interop (Implicit P/Invoke)](../dotnet/using-cpp-interop-implicit-pinvoke.md)
1414

15-
- [How to: Marshal Callbacks and Delegates By Using C++ Interop](../dotnet/how-to-marshal-callbacks-and-delegates-by-using-cpp-interop.md)
15+
- [How to: Marshal callbacks and delegates by using C++ Interop](../dotnet/how-to-marshal-callbacks-and-delegates-by-using-cpp-interop.md)
1616

17-
Unmanaged APIs that take functions pointers as arguments can be called from managed code with a managed delegate in place of the native function pointer. The compiler automatically marshals the delegate to unmanaged functions as a function pointer and inserts the necessary managed/unmanaged transition code.
17+
Unmanaged APIs that take functions pointers as arguments can be called from managed code by using a managed delegate in place of the native function pointer. The compiler automatically marshals the delegate to unmanaged functions as a function pointer. It inserts the necessary managed/unmanaged transition code.
1818

1919
## Example
2020

21-
The following code consists of an unmanaged and a managed module. The unmanaged module is a DLL that defines a function called TakesCallback that accepts a function pointer. This address is used to execute the function.
22-
23-
The managed module defines a delegate that is marshaled to the native code as a function pointer and uses the <xref:System.Runtime.InteropServices.DllImportAttribute> attribute to expose the native TakesCallback function to the managed code. In the main function, an instance of the delegate is created and passed to the TakesCallback function. The program output demonstrates that this function gets executed by the native TakesCallback function.
24-
25-
The managed function suppresses garbage collection for the managed delegate to prevent .NET Framework garbage collection from relocating the delegate while the native function executes.
21+
The following code consists of an unmanaged and a managed module. The unmanaged module is a DLL that defines a function called `TakesCallback` that accepts a function pointer. This address is used to execute the function.
2622

2723
```cpp
2824
// TraditionalDll5.cpp
@@ -48,6 +44,10 @@ int TakesCallback(CALLBACK fp, int n) {
4844
}
4945
```
5046
47+
The managed module defines a delegate that's marshaled to the native code as a function pointer. It uses the <xref:System.Runtime.InteropServices.DllImportAttribute> attribute to expose the native `TakesCallback` function to the managed code. In the `main` function, an instance of the delegate is created and passed to the `TakesCallback` function. The program output demonstrates that this function gets executed by the native `TakesCallback` function.
48+
49+
The managed function suppresses garbage collection for the managed delegate to prevent .NET Framework garbage collection from relocating the delegate while the native function executes.
50+
5151
```cpp
5252
// MarshalDelegate.cpp
5353
// compile with: /clr
@@ -76,8 +76,8 @@ int main() {
7676
}
7777
```
7878

79-
Note that no portion of the DLL is exposed to the managed code using the traditional #include directive. In fact, the DLL is accessed at run time only, so problems with functions imported with <xref:System.Runtime.InteropServices.DllImportAttribute> will not be detected at compile time.
79+
No portion of the DLL is exposed to the managed code using the traditional `#include` directive. In fact, the DLL is accessed at runtime only, so problems with functions imported by using <xref:System.Runtime.InteropServices.DllImportAttribute> can't be detected at compile time.
8080

8181
## See also
8282

83-
[Using Explicit PInvoke in C++ (DllImport Attribute)](../dotnet/using-explicit-pinvoke-in-cpp-dllimport-attribute.md)
83+
[Using explicit P/Invoke in C++ (`DllImport` attribute)](../dotnet/using-explicit-pinvoke-in-cpp-dllimport-attribute.md)

docs/dotnet/how-to-marshal-strings-using-pinvoke.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
---
2-
description: "Learn more about: How to: Marshal Strings Using PInvoke"
3-
title: "How to: Marshal Strings Using PInvoke"
2+
description: "Learn more about: How to: Marshal strings using P/Invoke"
3+
title: "How to: Marshal strings using P/Invoke"
44
ms.custom: "get-started-article"
5-
ms.date: "09/09/2016"
5+
ms.date: 06/29/2022
66
helpviewer_keywords: ["interop [C++], strings", "marshaling [C++], strings", "data marshaling [C++], strings", "platform invoke [C++], strings"]
77
ms.assetid: bcc75733-7337-4d9b-b1e9-b95a98256088
88
---
9-
# How to: Marshal Strings Using PInvoke
9+
# How to: Marshal strings using P/Invoke
1010

11-
This topic explains how native functions that accept C-style strings can be called using the CLR string type System::String using .NET Framework Platform Invoke support. Visual C++ programmers are encouraged to use the C++ Interop features instead (when possible) because P/Invoke provides little compile-time error reporting, is not type-safe, and can be tedious to implement. If the unmanaged API is packaged as a DLL, and the source code is not available, then P/Invoke is the only option, but otherwise see [Using C++ Interop (Implicit PInvoke)](../dotnet/using-cpp-interop-implicit-pinvoke.md).
11+
Native functions that accept C-style strings can be called using the CLR string type `System::String` by using .NET Framework Platform Invoke (P/Invoke) support. We encourage you to use the C++ Interop features instead of P/Invoke when possible. because P/Invoke provides little compile-time error reporting, isn't type-safe, and can be tedious to implement. If the unmanaged API is packaged as a DLL, and the source code isn't available, then P/Invoke is the only option. Otherwise, see [Using C++ Interop (Implicit P/Invoke)](../dotnet/using-cpp-interop-implicit-pinvoke.md).
1212

1313
Managed and unmanaged strings are laid out differently in memory, so passing strings from managed to unmanaged functions requires the <xref:System.Runtime.InteropServices.MarshalAsAttribute> attribute to instruct the compiler to insert the required conversion mechanisms for marshaling the string data correctly and safely.
1414

15-
As with functions that use only intrinsic data types, <xref:System.Runtime.InteropServices.DllImportAttribute> is used to declare managed entry points into the native functions, but--for passing strings--instead of defining these entry points as taking C-style strings, a handle to the <xref:System.String> type can be used instead. This prompts the compiler to insert code that performs the required conversion. For each function argument in an unmanaged function that takes a string, the <xref:System.Runtime.InteropServices.MarshalAsAttribute> attribute should be used to indicate that the String object should be marshaled to the native function as a C-style string.
15+
As with functions that use only intrinsic data types, <xref:System.Runtime.InteropServices.DllImportAttribute> is used to declare managed entry points into the native functions. Functions that pass strings can use a handle to the <xref:System.String> type instead of defining these entry points as taking C-style strings. Using this type prompts the compiler to insert code that performs the required conversion. For each function argument in an unmanaged function that takes a string, use the <xref:System.Runtime.InteropServices.MarshalAsAttribute> attribute to indicate that the `String` object should be marshaled to the native function as a C-style string.
1616

17-
The marshaler wraps the call to the unmanaged function in a hidden wrapper routine that pins and copies the managed string into a locally allocated string in the unmanaged context, which then is passed to the unmanaged function. When the unmanaged function returns, the wrapper either deletes the resource, or if it was on the stack, it is reclaimed when the wrapper goes out of scope. The unmanaged function is not responsible for this memory. The unmanaged code only creates and deletes memory in the heap set up by its own CRT, so there is never an issue with the marshaller using a different CRT version.
17+
The marshaler wraps the call to the unmanaged function in a hidden wrapper routine. The wrapper routine pins and copies the managed string into a locally allocated string in the unmanaged context. The local copy is then passed to the unmanaged function. When the unmanaged function returns, the wrapper deletes the resource. Or, if it was on the stack, it's reclaimed when the wrapper goes out of scope. The unmanaged function isn't responsible for this memory. The unmanaged code only creates and deletes memory in the heap set up by its own CRT, so there's never an issue with the marshaller using a different CRT version.
1818

1919
If your unmanaged function returns a string, either as a return value or an out parameter, the marshaler copies it into a new managed string, and then releases the memory. For more information, see [Default Marshaling Behavior](/dotnet/framework/interop/default-marshaling-behavior) and [Marshaling Data with Platform Invoke](/dotnet/framework/interop/marshaling-data-with-platform-invoke).
2020

2121
## Example
2222

23-
The following code consists of a unmanaged and a managed module. The unmanaged module is a DLL that defines a function called TakesAString that accepts a C-style ANSI string in the form of a char*. The managed module is a command-line application that imports the TakesAString function, but defines it as taking a managed System.String instead of a char\*. The <xref:System.Runtime.InteropServices.MarshalAsAttribute> attribute is used to indicate how the managed string should be marshaled when TakesAString is called.
23+
The following code consists of an unmanaged module and a managed module. The unmanaged module is a DLL that defines a function called `TakesAString`. `TakesAString` accepts a C-style narrow string in the form of a `char*`.
2424

2525
```cpp
2626
// TraditionalDll2.cpp
@@ -47,6 +47,8 @@ void TakesAString(char* p) {
4747
}
4848
```
4949
50+
The managed module is a command-line application that imports the `TakesAString` function, but defines it as taking a managed `System.String` instead of a `char*`. The <xref:System.Runtime.InteropServices.MarshalAsAttribute> attribute is used to indicate how the managed string should be marshaled when `TakesAString` is called.
51+
5052
```cpp
5153
// MarshalString.cpp
5254
// compile with: /clr
@@ -62,16 +64,16 @@ value struct TraditionalDLL
6264
6365
int main() {
6466
String^ s = gcnew String("sample string");
65-
Console::WriteLine("[managed] passing managed string to unmanaged function...");
67+
Console::WriteLine("[managed] passing managed string to unmanaged function...");
6668
TraditionalDLL::TakesAString(s);
6769
Console::WriteLine("[managed] {0}", s);
6870
}
6971
```
7072

71-
This technique causes a copy of the string to be constructed on the unmanaged heap, so changes made to the string by the native function will not be reflected in the managed copy of the string.
73+
This technique constructs a copy of the string on the unmanaged heap, so changes made to the string by the native function won't be reflected in the managed copy of the string.
7274

73-
Note that no portion of the DLL is exposed to the managed code via the traditional #include directive. In fact, the DLL is accessed at runtime only, so problems with functions imported with `DllImport` will not be detected at compile time.
75+
No portion of the DLL is exposed to the managed code by the traditional `#include` directive. In fact, the DLL is accessed at runtime only, so problems in functions imported by using `DllImport` aren't detected at compile time.
7476

7577
## See also
7678

77-
[Using Explicit PInvoke in C++ (DllImport Attribute)](../dotnet/using-explicit-pinvoke-in-cpp-dllimport-attribute.md)
79+
[Using explicit P/Invoke in C++ (`DllImport` attribute)](../dotnet/using-explicit-pinvoke-in-cpp-dllimport-attribute.md)

0 commit comments

Comments
 (0)