Wrapping an IntPtr in a Struct for safer Interop

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
4
down vote

favorite












Consider the following C#/C interop scenario:



public static extern IntPtr lua_newstate();
public static extern void lua_close(IntPtr state);

IntPtr luaState = lua_newstate();
// use lua ...
lua_close(luaState)


Obviously this works well enough, however there's a fringe possibility that an IntPtr not pointing to a lua state could be passed to lua_close, since it accepts any IntPtr.



I realized that it's possible to use the behavior of struct marshaling to make this interop a bit more type-safe



[StructLayout(LayoutKind.Sequential)]
public struct LuaState

public readonly IntPtr Pointer;


public static extern LuaState lua_newstate();
public static extern void lua_close(LuaState state);

LuaState luaState = lua_newstate();
// use lua ...
lua_close(luaState)


Since LuaState contains only an IntPtr, the marshaler happily converts the native pointer returned by lua_newstate to an instance of LuaState, and will also quite happily convert a LuaState struct to a native pointer when passed back to a native function.



This essentially creates a typed pointer. There is a cost associated with passing LuaState though the Marshaling system instead of passing IntPtr directly to the native side, but in testing the cost appears to be negligible.



Questions: Does using LuaState to create a typed wrapper for IntPtr in this way raise any red flags? Has anyone done something similar and run into issues?







share|improve this question





















  • Perhaps consider SafeAccessTokenHandle (msdn.microsoft.com/en-us/library/…) ?
    – Jesse C. Slicer
    Mar 6 at 18:44
















up vote
4
down vote

favorite












Consider the following C#/C interop scenario:



public static extern IntPtr lua_newstate();
public static extern void lua_close(IntPtr state);

IntPtr luaState = lua_newstate();
// use lua ...
lua_close(luaState)


Obviously this works well enough, however there's a fringe possibility that an IntPtr not pointing to a lua state could be passed to lua_close, since it accepts any IntPtr.



I realized that it's possible to use the behavior of struct marshaling to make this interop a bit more type-safe



[StructLayout(LayoutKind.Sequential)]
public struct LuaState

public readonly IntPtr Pointer;


public static extern LuaState lua_newstate();
public static extern void lua_close(LuaState state);

LuaState luaState = lua_newstate();
// use lua ...
lua_close(luaState)


Since LuaState contains only an IntPtr, the marshaler happily converts the native pointer returned by lua_newstate to an instance of LuaState, and will also quite happily convert a LuaState struct to a native pointer when passed back to a native function.



This essentially creates a typed pointer. There is a cost associated with passing LuaState though the Marshaling system instead of passing IntPtr directly to the native side, but in testing the cost appears to be negligible.



Questions: Does using LuaState to create a typed wrapper for IntPtr in this way raise any red flags? Has anyone done something similar and run into issues?







share|improve this question





















  • Perhaps consider SafeAccessTokenHandle (msdn.microsoft.com/en-us/library/…) ?
    – Jesse C. Slicer
    Mar 6 at 18:44












up vote
4
down vote

favorite









up vote
4
down vote

favorite











Consider the following C#/C interop scenario:



public static extern IntPtr lua_newstate();
public static extern void lua_close(IntPtr state);

IntPtr luaState = lua_newstate();
// use lua ...
lua_close(luaState)


Obviously this works well enough, however there's a fringe possibility that an IntPtr not pointing to a lua state could be passed to lua_close, since it accepts any IntPtr.



I realized that it's possible to use the behavior of struct marshaling to make this interop a bit more type-safe



[StructLayout(LayoutKind.Sequential)]
public struct LuaState

public readonly IntPtr Pointer;


public static extern LuaState lua_newstate();
public static extern void lua_close(LuaState state);

LuaState luaState = lua_newstate();
// use lua ...
lua_close(luaState)


Since LuaState contains only an IntPtr, the marshaler happily converts the native pointer returned by lua_newstate to an instance of LuaState, and will also quite happily convert a LuaState struct to a native pointer when passed back to a native function.



This essentially creates a typed pointer. There is a cost associated with passing LuaState though the Marshaling system instead of passing IntPtr directly to the native side, but in testing the cost appears to be negligible.



Questions: Does using LuaState to create a typed wrapper for IntPtr in this way raise any red flags? Has anyone done something similar and run into issues?







share|improve this question













Consider the following C#/C interop scenario:



public static extern IntPtr lua_newstate();
public static extern void lua_close(IntPtr state);

IntPtr luaState = lua_newstate();
// use lua ...
lua_close(luaState)


Obviously this works well enough, however there's a fringe possibility that an IntPtr not pointing to a lua state could be passed to lua_close, since it accepts any IntPtr.



I realized that it's possible to use the behavior of struct marshaling to make this interop a bit more type-safe



[StructLayout(LayoutKind.Sequential)]
public struct LuaState

public readonly IntPtr Pointer;


public static extern LuaState lua_newstate();
public static extern void lua_close(LuaState state);

LuaState luaState = lua_newstate();
// use lua ...
lua_close(luaState)


Since LuaState contains only an IntPtr, the marshaler happily converts the native pointer returned by lua_newstate to an instance of LuaState, and will also quite happily convert a LuaState struct to a native pointer when passed back to a native function.



This essentially creates a typed pointer. There is a cost associated with passing LuaState though the Marshaling system instead of passing IntPtr directly to the native side, but in testing the cost appears to be negligible.



Questions: Does using LuaState to create a typed wrapper for IntPtr in this way raise any red flags? Has anyone done something similar and run into issues?









share|improve this question












share|improve this question




share|improve this question








edited Mar 6 at 17:16









hjpotter92

4,97611539




4,97611539









asked Feb 28 at 21:53









Riley G

211




211











  • Perhaps consider SafeAccessTokenHandle (msdn.microsoft.com/en-us/library/…) ?
    – Jesse C. Slicer
    Mar 6 at 18:44
















  • Perhaps consider SafeAccessTokenHandle (msdn.microsoft.com/en-us/library/…) ?
    – Jesse C. Slicer
    Mar 6 at 18:44















Perhaps consider SafeAccessTokenHandle (msdn.microsoft.com/en-us/library/…) ?
– Jesse C. Slicer
Mar 6 at 18:44




Perhaps consider SafeAccessTokenHandle (msdn.microsoft.com/en-us/library/…) ?
– Jesse C. Slicer
Mar 6 at 18:44










1 Answer
1






active

oldest

votes

















up vote
5
down vote













I think, I would experiment with a safe or smart pointer approach in a way like this:



public sealed class LuaHandle : IDisposable

private static extern IntPtr lua_newstate();
private static extern void lua_close(IntPtr state);

private IntPtr m_handle = IntPtr.Zero;

public LuaHandle()

m_handle = lua_newstate();


public IntPtr Handle => m_handle;


public void Dispose()

if (m_handle != IntPtr.Zero)

lua_close(m_handle);


m_handle = IntPtr.Zero;





Usage:



 using (LuaHandle luaHandle = new LuaHandle())

// do something with luaHandle.Handle



In this way you - as a client of LuaHandle - don't have to deal with the extern api's at all and no invalid IntPtr can be past as argument to lua_close()






share|improve this answer























  • Hadn't considered a wrapper like this. Thanks!
    – Riley G
    Mar 5 at 19:08










  • Typo at public selaed?
    – hjpotter92
    Mar 6 at 17:16










  • @hjpotter92 - Thanks!
    – Henrik Hansen
    Mar 6 at 17:48










Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188563%2fwrapping-an-intptr-in-a-struct-for-safer-interop%23new-answer', 'question_page');

);

Post as a guest






























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
5
down vote













I think, I would experiment with a safe or smart pointer approach in a way like this:



public sealed class LuaHandle : IDisposable

private static extern IntPtr lua_newstate();
private static extern void lua_close(IntPtr state);

private IntPtr m_handle = IntPtr.Zero;

public LuaHandle()

m_handle = lua_newstate();


public IntPtr Handle => m_handle;


public void Dispose()

if (m_handle != IntPtr.Zero)

lua_close(m_handle);


m_handle = IntPtr.Zero;





Usage:



 using (LuaHandle luaHandle = new LuaHandle())

// do something with luaHandle.Handle



In this way you - as a client of LuaHandle - don't have to deal with the extern api's at all and no invalid IntPtr can be past as argument to lua_close()






share|improve this answer























  • Hadn't considered a wrapper like this. Thanks!
    – Riley G
    Mar 5 at 19:08










  • Typo at public selaed?
    – hjpotter92
    Mar 6 at 17:16










  • @hjpotter92 - Thanks!
    – Henrik Hansen
    Mar 6 at 17:48














up vote
5
down vote













I think, I would experiment with a safe or smart pointer approach in a way like this:



public sealed class LuaHandle : IDisposable

private static extern IntPtr lua_newstate();
private static extern void lua_close(IntPtr state);

private IntPtr m_handle = IntPtr.Zero;

public LuaHandle()

m_handle = lua_newstate();


public IntPtr Handle => m_handle;


public void Dispose()

if (m_handle != IntPtr.Zero)

lua_close(m_handle);


m_handle = IntPtr.Zero;





Usage:



 using (LuaHandle luaHandle = new LuaHandle())

// do something with luaHandle.Handle



In this way you - as a client of LuaHandle - don't have to deal with the extern api's at all and no invalid IntPtr can be past as argument to lua_close()






share|improve this answer























  • Hadn't considered a wrapper like this. Thanks!
    – Riley G
    Mar 5 at 19:08










  • Typo at public selaed?
    – hjpotter92
    Mar 6 at 17:16










  • @hjpotter92 - Thanks!
    – Henrik Hansen
    Mar 6 at 17:48












up vote
5
down vote










up vote
5
down vote









I think, I would experiment with a safe or smart pointer approach in a way like this:



public sealed class LuaHandle : IDisposable

private static extern IntPtr lua_newstate();
private static extern void lua_close(IntPtr state);

private IntPtr m_handle = IntPtr.Zero;

public LuaHandle()

m_handle = lua_newstate();


public IntPtr Handle => m_handle;


public void Dispose()

if (m_handle != IntPtr.Zero)

lua_close(m_handle);


m_handle = IntPtr.Zero;





Usage:



 using (LuaHandle luaHandle = new LuaHandle())

// do something with luaHandle.Handle



In this way you - as a client of LuaHandle - don't have to deal with the extern api's at all and no invalid IntPtr can be past as argument to lua_close()






share|improve this answer















I think, I would experiment with a safe or smart pointer approach in a way like this:



public sealed class LuaHandle : IDisposable

private static extern IntPtr lua_newstate();
private static extern void lua_close(IntPtr state);

private IntPtr m_handle = IntPtr.Zero;

public LuaHandle()

m_handle = lua_newstate();


public IntPtr Handle => m_handle;


public void Dispose()

if (m_handle != IntPtr.Zero)

lua_close(m_handle);


m_handle = IntPtr.Zero;





Usage:



 using (LuaHandle luaHandle = new LuaHandle())

// do something with luaHandle.Handle



In this way you - as a client of LuaHandle - don't have to deal with the extern api's at all and no invalid IntPtr can be past as argument to lua_close()







share|improve this answer















share|improve this answer



share|improve this answer








edited Mar 6 at 17:48


























answered Mar 1 at 7:51









Henrik Hansen

3,8931417




3,8931417











  • Hadn't considered a wrapper like this. Thanks!
    – Riley G
    Mar 5 at 19:08










  • Typo at public selaed?
    – hjpotter92
    Mar 6 at 17:16










  • @hjpotter92 - Thanks!
    – Henrik Hansen
    Mar 6 at 17:48
















  • Hadn't considered a wrapper like this. Thanks!
    – Riley G
    Mar 5 at 19:08










  • Typo at public selaed?
    – hjpotter92
    Mar 6 at 17:16










  • @hjpotter92 - Thanks!
    – Henrik Hansen
    Mar 6 at 17:48















Hadn't considered a wrapper like this. Thanks!
– Riley G
Mar 5 at 19:08




Hadn't considered a wrapper like this. Thanks!
– Riley G
Mar 5 at 19:08












Typo at public selaed?
– hjpotter92
Mar 6 at 17:16




Typo at public selaed?
– hjpotter92
Mar 6 at 17:16












@hjpotter92 - Thanks!
– Henrik Hansen
Mar 6 at 17:48




@hjpotter92 - Thanks!
– Henrik Hansen
Mar 6 at 17:48












 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188563%2fwrapping-an-intptr-in-a-struct-for-safer-interop%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Greedy Best First Search implementation in Rust

Function to Return a JSON Like Objects Using VBA Collections and Arrays

C++11 CLH Lock Implementation