Skip to content
This repository has been archived by the owner on Jan 13, 2024. It is now read-only.

Support for x64 - Tech Debt #98

Open
mahee96 opened this issue Nov 20, 2022 · 3 comments
Open

Support for x64 - Tech Debt #98

mahee96 opened this issue Nov 20, 2022 · 3 comments
Assignees
Labels

Comments

@mahee96
Copy link
Collaborator

mahee96 commented Nov 20, 2022

Problem Statement:

Trying to support x64 features into a plugin pack which was initially designed to be target x86 arch/runtime only under .NET 4.0 framework.

The plugin pack is a bridge that externalizes the APIs from unmanaged c/c++ native windows application to the managed CLR side such that the plugin developer can use .NET side of the application's API instead.
This is done by using UnmanagedExports where the IL is hacked to match the native binary's ABI.

In doing so, the marshalling needs to support both 32 bit and 64 bit width data.
In native code such as C++ the type 'int' has dynamic width x86(32-bits) and x64(64-bits) based on compilation type (x86 builds or x64 builds).

But in .NET, int is 32 bit wide and long is 64 bit wide irrespective of build type(arch/platform).

Hence a dynamic type would be required which will accommodate both 32 bits and 64 bits based on build types.

Approach-1:

This is accomplished by using "IntPtr".
This IntPtr is useful in defining structural integrity of marshalled "structures" from unmanaged size to managed side.

But in terms of API that are supplied by the plugin pack, using IntPtr everywhere for int/intptr_t in unmanaged API, complicates everything.

Disadvantages of using "IntPtr"

  1. APIs from native code and managed code will vary, since IntPtr is class type whereas int/void* types in native side are primitives that doesn't require overloaded operators for basic arithmetic data or pointer arithmetic.
  2. IntPtr.Size property needs to be used everywhere by the plugin developer to query the current CLR execution env info (x86 or x64) and then decide to use "int" or "long" types.
    This decision will be done at Runtime.
  3. Runtime determination leads to lots of extra/duplicate codes on the plugin pack user side, that just differ by data types int(32bit)/long(64bit) with a bit of execution time overhead.

Advantages of using "IntPtr":

  1. Much of the coding burden is on the user of the plugin pack
  2. Though managed APIs differ from native APIs, the differences can be documented and maintained.
  3. Single codebase can be used for both x86 and x64 configs.

(Alternative) Approach-2:

Have separate codebases for x86(uses "int") and x64(uses "long") - compile and supply both binaries(x86 and x64) instead of supplying source code.

Disadvantages:

  1. Code duplication and maintenance for both codebases.
  2. Code deviation between bases.
  3. Two separate API sets need to be documented whereas native API documentation needs only one, because single codebase is used for both x86 and x64 builds.

Advantages:

  1. Less efforts on user side as data width is determined at compile time using explicit int/long Types.
  2. User may not run into unexpected integer overflows at runtime due to the plugin pack ie, guarantees type safety.
  3. Separate codebase and binaries ensure earlier detection of root cause compared to single codebase producing separate binaries.

(Alternate) Approach-3: (Infeasible due to duplicate API signatures issue)

Perform the platform type determination at the plugin pack side by having 2 sets of API (with int and long types) and throw "Exception ("Unsupported platform")" when code path takes through non-applicable API(int) in current context(x64).

Disadvantages:

  1. (compilation issue) duplicate API definition since API differing by return types are non-unique.
  2. Two sets of API will be publicly visible.
  3. Unexpected Runtime surprises for the consumer/user of plugin pack.

Advantages:

  1. Single codebase.

Proposed Solution:

Out of all the 3 approaches, I see the Approach-2 to be better suited (separate codebase and respective assemblies)

  • By doing so, we can limit the compilation type to x86 or x64 only by modifying the .csproj along with its separate code bases.
  • When packaged into Nuget package, the plugin pack user only needs the final assembly/binary which we can release, instead of leaving the user to compile from source.

@kbilsted, provide your feedback on the proposal

@mahee96 mahee96 pinned this issue Nov 20, 2022
@mahee96
Copy link
Collaborator Author

mahee96 commented Nov 20, 2022

See our previous discussion regarding the same in PR #75

@gandarez
Copy link
Contributor

Any update on this?

@mahee96
Copy link
Collaborator Author

mahee96 commented Dec 8, 2022

@kbilsted If by any chance did you get a chance to review the approaches laid out?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants