diff --git a/API/RainmeterAPI.cs b/API/RainmeterAPI.cs
index 72454c4..4490dd1 100644
--- a/API/RainmeterAPI.cs
+++ b/API/RainmeterAPI.cs
@@ -531,6 +531,60 @@ public void LogF(LogType type, string format, params Object[] args)
RmLog(this.m_Rm, type, string.Format(format, args));
}
}
+
+ ///
+ /// Helper for returning strings back to Rainmeter as an IntPtr.
+ ///
+ ///
+ ///
+ /// [DllExport]
+ /// public static IntPtr GetString(IntPtr data)
+ /// {
+ /// return Rainmeter.StringBuffer.Update("hello");
+ /// }
+ ///
+ ///
+ public sealed class StringBuffer
+ {
+ private static readonly StringBuffer s_Instance = new StringBuffer();
+
+ private IntPtr m_Buffer = IntPtr.Zero;
+
+ static StringBuffer()
+ {
+ }
+
+ private StringBuffer()
+ {
+ }
+
+ ~StringBuffer()
+ {
+ FreeBuffer();
+ }
+
+ private void FreeBuffer()
+ {
+ if (m_Buffer != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(m_Buffer);
+ m_Buffer = IntPtr.Zero;
+ }
+ }
+
+ public static IntPtr Update(string value)
+ {
+ s_Instance.FreeBuffer();
+ s_Instance.m_Buffer = value != null ? Marshal.StringToHGlobalUni(value) : IntPtr.Zero;
+ return s_Instance.m_Buffer;
+ }
+
+ public static IntPtr Get()
+ {
+ return s_Instance.m_Buffer;
+ }
+ }
+
///
/// Dummy attribute to mark method as exported for DllExporter.exe.
///
diff --git a/C#/PluginEmpty/PluginEmpty.cs b/C#/PluginEmpty/PluginEmpty.cs
index ecfa475..3064d11 100644
--- a/C#/PluginEmpty/PluginEmpty.cs
+++ b/C#/PluginEmpty/PluginEmpty.cs
@@ -5,10 +5,9 @@
// Overview: This is a blank canvas on which to build your plugin.
-// Note: GetString, ExecuteBang and an unnamed function for use as a section variable
+// Note: GetString, ExecuteBang and MyCustomFunction for use as a section variable
// have been commented out. If you need GetString, ExecuteBang, and/or section variables
-// and you have read what they are used for from the SDK docs, uncomment the function(s)
-// and/or add a function name to use for the section variable function(s).
+// and you have read what they are used for from the SDK docs, uncomment the function(s).
// Otherwise leave them commented out (or get rid of them)!
namespace PluginEmpty
@@ -19,7 +18,8 @@ static public implicit operator Measure(IntPtr data)
{
return (Measure)GCHandle.FromIntPtr(data).Target;
}
- public IntPtr buffer = IntPtr.Zero;
+
+ // Include your measure data/functions here.
}
public class Plugin
@@ -35,10 +35,7 @@ public static void Initialize(ref IntPtr data, IntPtr rm)
public static void Finalize(IntPtr data)
{
Measure measure = (Measure)data;
- if (measure.buffer != IntPtr.Zero)
- {
- Marshal.FreeHGlobal(measure.buffer);
- }
+
GCHandle.FromIntPtr(data).Free();
}
@@ -52,7 +49,6 @@ public static void Reload(IntPtr data, IntPtr rm, ref double maxValue)
public static double Update(IntPtr data)
{
Measure measure = (Measure)data;
-
return 0.0;
}
@@ -60,15 +56,7 @@ public static double Update(IntPtr data)
//public static IntPtr GetString(IntPtr data)
//{
// Measure measure = (Measure)data;
- // if (measure.buffer != IntPtr.Zero)
- // {
- // Marshal.FreeHGlobal(measure.buffer);
- // measure.buffer = IntPtr.Zero;
- // }
- //
- // measure.buffer = Marshal.StringToHGlobalUni("");
- //
- // return measure.buffer;
+ // return Rainmeter.StringBuffer.Update("");
//}
//[DllExport]
@@ -78,19 +66,10 @@ public static double Update(IntPtr data)
//}
//[DllExport]
- //public static IntPtr (IntPtr data, int argc,
+ //public static IntPtr MyCustomFunction(IntPtr data, int argc,
// [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] string[] argv)
//{
- // Measure measure = (Measure)data;
- // if (measure.buffer != IntPtr.Zero)
- // {
- // Marshal.FreeHGlobal(measure.buffer);
- // measure.buffer = IntPtr.Zero;
- // }
- //
- // measure.buffer = Marshal.StringToHGlobalUni("");
- //
- // return measure.buffer;
+ // return Rainmeter.StringBuffer.Update("");
//}
}
}
diff --git a/C#/PluginSectionVariables/PluginSectionVariables.cs b/C#/PluginSectionVariables/PluginSectionVariables.cs
index 0cb11c0..e2a8f4b 100644
--- a/C#/PluginSectionVariables/PluginSectionVariables.cs
+++ b/C#/PluginSectionVariables/PluginSectionVariables.cs
@@ -1,19 +1,19 @@
/*
-Copyright (C) 2017 Trevor Hamilton
+ Copyright (C) 2017 Trevor Hamilton
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
@@ -68,8 +68,8 @@ static public implicit operator Measure(IntPtr data)
{
return (Measure)GCHandle.FromIntPtr(data).Target;
}
- public string inputStr; //The string returned in GetString is stored here
- public IntPtr buffer; //Prevent marshalAs from causing memory leaks by clearing this before assigning
+
+ public string inputStr;
}
public class Plugin
@@ -87,7 +87,6 @@ public static void Reload(IntPtr data, IntPtr rm, ref double maxValue)
Measure measure = (Measure)data;
Rainmeter.API api = (Rainmeter.API)rm;
- //Read measure for an Input string
measure.inputStr = api.ReadString("Input", "");
}
@@ -102,14 +101,7 @@ public static double Update(IntPtr data)
public static IntPtr GetString(IntPtr data)
{
Measure measure = (Measure)data;
- if (measure.buffer != IntPtr.Zero)
- {
- Marshal.FreeHGlobal(measure.buffer);
- measure.buffer = IntPtr.Zero;
- }
-
- measure.buffer = Marshal.StringToHGlobalUni(measure.inputStr);
- return measure.buffer;
+ return Rainmeter.StringBuffer.Update(measure.inputStr);
}
[DllExport]
@@ -117,23 +109,15 @@ public static IntPtr ToUpper(IntPtr data, int argc,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] string[] argv)
{
Measure measure = (Measure)data;
- if (measure.buffer != IntPtr.Zero)
- {
- Marshal.FreeHGlobal(measure.buffer);
- measure.buffer = IntPtr.Zero;
- }
- //If we are given one or more arguments convert to uppercase the first one
+ // If we are given one or more arguments convert to uppercase the first one
if (argc > 0)
{
- measure.buffer = Marshal.StringToHGlobalUni(argv[0].ToUpper());
- }
- //If we are given no arguments convert to uppercase the string we recived with the input option
- else
- {
- measure.buffer = Marshal.StringToHGlobalUni(measure.inputStr.ToUpper());
+ return Rainmeter.StringBuffer.Update(argv[0].ToUpper());
}
- return measure.buffer;
+
+ // If we are given no arguments convert to uppercase the string we recived with the input option
+ return Rainmeter.StringBuffer.Update(measure.inputStr.ToUpper());
}
[DllExport]
@@ -141,33 +125,19 @@ public static IntPtr ToLower(IntPtr data, int argc,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] string[] argv)
{
Measure measure = (Measure)data;
- if (measure.buffer != IntPtr.Zero)
- {
- Marshal.FreeHGlobal(measure.buffer);
- measure.buffer = IntPtr.Zero;
- }
- //If we are given one or more arguments convert to uppercase the first one
if (argc > 0)
{
- measure.buffer = Marshal.StringToHGlobalUni(argv[0].ToUpper());
- }
- //If we are given no arguments convert to uppercase the string we recived with the input option
- else
- {
- measure.buffer = Marshal.StringToHGlobalUni(measure.inputStr.ToLower());
+ return Rainmeter.StringBuffer.Update(argv[0].ToUpper());
}
- return measure.buffer;
+
+ return Rainmeter.StringBuffer.Update(measure.inputStr.ToLower());
}
[DllExport]
public static void Finalize(IntPtr data)
{
Measure measure = (Measure)data;
- if (measure.buffer != IntPtr.Zero)
- {
- Marshal.FreeHGlobal(measure.buffer);
- }
GCHandle.FromIntPtr(data).Free();
}
}
diff --git a/C#/PluginSystemVersion/PluginSystemVersion.cs b/C#/PluginSystemVersion/PluginSystemVersion.cs
index 5d07c4c..e908375 100644
--- a/C#/PluginSystemVersion/PluginSystemVersion.cs
+++ b/C#/PluginSystemVersion/PluginSystemVersion.cs
@@ -161,8 +161,6 @@ internal string GetString()
public static class Plugin
{
- static IntPtr StringBuffer = IntPtr.Zero;
-
[DllExport]
public static void Initialize(ref IntPtr data, IntPtr rm)
{
@@ -173,12 +171,6 @@ public static void Initialize(ref IntPtr data, IntPtr rm)
public static void Finalize(IntPtr data)
{
GCHandle.FromIntPtr(data).Free();
-
- if (StringBuffer != IntPtr.Zero)
- {
- Marshal.FreeHGlobal(StringBuffer);
- StringBuffer = IntPtr.Zero;
- }
}
[DllExport]
@@ -199,19 +191,7 @@ public static double Update(IntPtr data)
public static IntPtr GetString(IntPtr data)
{
Measure measure = (Measure)GCHandle.FromIntPtr(data).Target;
- if (StringBuffer != IntPtr.Zero)
- {
- Marshal.FreeHGlobal(StringBuffer);
- StringBuffer = IntPtr.Zero;
- }
-
- string stringValue = measure.GetString();
- if (stringValue != null)
- {
- StringBuffer = Marshal.StringToHGlobalUni(stringValue);
- }
-
- return StringBuffer;
+ return Rainmeter.StringBuffer.Update(measure.GetString());
}
}
}