Forum


Notice to all users

We are migrating towards a new forum system located at community.teamspeak.com, as such this forum will become read-only on January 29, 2020

Page 1 of 2 12 LastLast
Results 1 to 15 of 30
  1. #1
    Join Date
    December 2009
    Location
    Deutschland
    Posts
    35

    C# Plugin Wrapper

    Hi,
    after I've seen many people here wanting to write their plugin in .Net, I've managed to find a good way to accomplish this. At first I've tried it myself creating the Chat-TTS-Plugin, and now I'm wrapping everything into a nice packet ready to develop plugins. A user named Skeletr0n is helping me doing all the nasty recoding work etc. As we want to deliver a clean solution, we've layed aside our own testing code to write a consistent package from the ground up, so the project is still at it's start. The newest version can be checked out at our svn-directory: http://ts3tts.zockprog.net/svn/TS3TTS/TS3Plugin/; but as I said before we're still working on it (so don't be sad if we haven't implemented the function you need right now - it'll follow). If there are any VB.Net programmers interested in this: I don't know how to use this project in VB.Net, if you want to use it you have to somehow transfer our work to VB.Net.
    Special thanks go to Robert Giesecke for creating a VS Solution so you don't have to decompile to IL and recompile your whole project everytime you build it and to SpiritOffice for spotting a tiny mistake making the x86-plugins crash and his help improving the function/fixing mistakes.
    Last edited by addilind; October 3rd, 2010 at 02:07 PM.

  2. #2
    Join Date
    August 2009
    Location
    Australia
    Posts
    26
    Very cool :-)

    Will be keeping an eye on this project.

  3. #3
    Join Date
    January 2010
    Location
    Germany
    Posts
    17
    Looks very good, although there are some "bugs":
    a) you need to put the unsafe keyword for the delegates using pointers (and therefor you need to compile it with the unsafe flag)
    b) vs2010 has a problem that there's a property called "Configure" and a method called so (and the property isn't used anywhere)

    And I have also a question:
    when I compile my plugin, there is a myplugin.dll in the bin-folder, a myplugin.dll in the bin\x86 folder and one in the bin\x64 folder.
    Do I have to distribute the ones in the subfolders or the one in the bin-folder?

  4. #4
    Join Date
    December 2009
    Location
    Deutschland
    Posts
    35
    @t-master:
    a. the delegates are still in work, and, believe me or not, it is possible without the unsafe keyword and compiler flag
    b. you need to distribute the dlls in the subfolders

  5. #5
    Join Date
    January 2010
    Location
    Germany
    Posts
    17
    Well, first vs2010 doesn't let me compile it without declaring those delegates unsafe and second don't you always have to use the unsafe-keyword when working with pointers in managed code?

  6. #6
    Join Date
    December 2009
    Location
    Deutschland
    Posts
    35
    First we haven't finished rewriting the delegate(which the program makes use of ONLY, take a closer look at Marshal.GetDelegateForFunctionPointer or at the Chat-TTS-Source, there I've enabled some functions) and so the stars making your compiler give you errors are only there because I've copy&pasted the C++ code and hadn't finished rewiting them.
    And second, as stated above, you don't need to work with pointers. Btw the newest release should compile without errors (and the warnings have to be ignored as they are only about the struct which is to be filled by TS3-Client is never set to any value by .Net) if you comment out the unfinshed lines in TS3FunctionsCallback.cs, even if you can't call any TS3Function right now.

  7. #7
    Join Date
    December 2009
    Location
    Deutschland
    Posts
    35
    Progress update
    [BTW: you can find the current sources on svn]
    What we've finished the basic structure, but still have to wrap all TS3Functions in a C#-Way(so the plugin-programmer doesn't need to work with IntPtr, Marshal etc.)
    The project is only thought to be used by experienced C#-programmers yet who can use the TS3Plugin.Wrapping.TS3FunctionsDirect(which contains the delegates as given by TS3) and tell us if we made any mistakes at the functions parameters. Furthermore you need to understand how to implement some functions temporarily (as in the moment you can only use Init, Shutdown and Configure without changing things in the wrapping-classes). It is not yet polished enough to enable every C#-beginner to write his plugin. (And anyone who can't use a svn client as well...)
    Last edited by addilind; October 2nd, 2010 at 01:10 PM.

  8. #8
    Join Date
    December 2009
    Location
    Germany
    Posts
    17
    there is a very important command missing: freeMemory. after every svn update i need to add this manual. would you write it in svn?

  9. #9
    Join Date
    December 2009
    Location
    Deutschland
    Posts
    35
    Of course, but do you allocate memory not handled by .Net Garbarge-Collector?
    Is there any method that gives you a something you need to free manual? If so please tell us so we can add that notice in the function comments, because most C#-Programmers won't free memory(including me, as I thought every variable used by a plugin gets checked by GC)
    EDIT: Took a closer look at the SDK-C#-Example and saw that you need to release the memory everytime you used a function with a "out"/"ref" parameter...
    And how do you implement it? Using an IntPtr as Parameter(as done in the SDK-Example)? I've implemented it that way in Revision 116.

    Current progress:
    Dealing with functions giving back an array of values, only working wrapped function is TS3Functions.getChannelClientList() in the moment.
    ToDo: Edit the type of array-return-refs to IntPtr(as it's an array in the moment, which doesn't work)
    Last edited by addilind; October 2nd, 2010 at 01:19 PM.

  10. #10
    Join Date
    December 2009
    Location
    Germany
    Posts
    17
    as i know every variable has a counter for number of references to it. if nothing references this variable then GB kills it. But it is only for DotNet only. The memory in TS functions was allocated in c++ (i think with "malloc()" or something else) and should be released with "free()"(wrapped in TS as freeMemory) command.

    if you work with unmanaged memory you should release all your allocations manualy. after you have used getClientSelfVariableAsString(........, ref IntPtr result) command und after you saved the string in managed variable(string STR = Marshal.PtrToStringAnsi(result);), you must call freeMemory(result).

    EDIT:
    the next problem:
    if you use something like IntPtr ptr = Marshal.StringToHGlobalAnsi(text); you should also release this allocated memory with "Marshal.FreeHGlobal(ptr)", because it is unmanaged allocation.

    EDIT2:
    Which command with array does not work for you? i can look at it

    EDIT3:-)
    you should call freeMemory only if your getClientSelfVariableAsString was ERROR_ok or it cause crash!
    Last edited by SpiritOffice; October 2nd, 2010 at 02:15 PM.

  11. #11
    Join Date
    December 2009
    Location
    Deutschland
    Posts
    35
    Ok, as you've propably already seen we're changing the TS3-Wrapper functions to free the allocated memory.
    About the arrays: The problem was I looked at http://msdn.microsoft.com/en-us/libr...=VS.85%29.aspx and just used the C# equivalent in the Delegate-definitions.
    This should work allright(haven't tested it really yet), but it doesn't work if you use the ref parameter on the array (see second example on msdn).
    I've already fixed getChannelClientList, but every other function returning an array needs to be fixed.

    If you want to, you can help as well, PM me for a SVN-Write-Account, help is always appreciated.

    Regarding your 3rd edit: If a function doesn't return Error_OK, an Exception is thrown=>the method will cancel

    But what about spawnNewServerConnectionHandler or getClientID for example? Is it mandatory to alway give an IntPtr to the function, copy its value to .Net and then release the Pointer?
    Because in the moment I let .Net convert the Pointer to an ulong/ushort on-the-fly, and therefore don't have a Pointer to release... I haven't got that much experience in C++ neither it's underlying structure so I could answer these problems myself...

    Edit: Another problem occured: In the functions where I get a pointer to an array, my method reading the array works fine. But if I try to release the pointer I received by TS3, the client crashes...
    Last edited by addilind; October 3rd, 2010 at 02:58 PM.

  12. #12
    Join Date
    December 2009
    Location
    Germany
    Posts
    17
    i didn't use such delegations, but in this project we don't need to create delegations for arrays. any user should not have to use pointers, so we don't need to recreate any of unmanaged structures. all we need to do is to take all pointers for result array, create our own managed array for user and release memory in teamspeak. for each ts3 command our function will be a bit different.

    for spawnNewServerConnectionHandler or getClientID you don't need to free the memory, because there are no pointers but variables.

    if you get a pointer to the array, you should call freememory for every field of this array. you can read it in client sdk manual at function getPlaybackModeList.

    EDIT:

    the function freeMemory is missing in ts3plugin_setFunctionPointers function, that is why the plugin crashes from time to time at freememory call.
    as example i wrote a wrapper function getCaptureModeList() with array return. i used offset 4 for the next item in array, but somebody should test it on 64bit system.
    [StructLayout(LayoutKind.Sequential)]
    public struct CaptureMode
    {
    public string modeID;
    public string name;
    }
    public static CaptureMode[] getCaptureModeList()
    {
    IntPtr ptr = IntPtr.Zero;
    if (TS3FunctionsDirect.getCaptureModeList(ref ptr) != (uint)Errors.ERROR_ok)
    {
    throw new Exception("TS3Functions.getCaptureModeList returned an error");
    }
    CaptureMode[] ret = new CaptureMode[0];
    int i = 0;
    IntPtr iteration;
    do
    {
    iteration = Marshal.ReadIntPtr(ptr, i);
    if (iteration == IntPtr.Zero) break;
    Array.Resize<CaptureMode>(ref ret, ret.Length + 1);
    ret[ret.Length - 1].modeID = Marshal.PtrToStringAnsi( Marshal.ReadIntPtr( iteration, 0));
    ret[ret.Length - 1].name = Marshal.PtrToStringAnsi( Marshal.ReadIntPtr( iteration, 4));
    TS3FunctionsDirect.freeMemory (Marshal.ReadIntPtr( iteration, 0));
    TS3FunctionsDirect.freeMemory (Marshal.ReadIntPtr( iteration, 4));
    TS3FunctionsDirect.freeMemory ( iteration);
    i += 4;
    } while (true);
    TS3FunctionsDirect.freeMemory(ptr);
    return ret;
    }
    Last edited by SpiritOffice; October 3rd, 2010 at 10:35 PM.

  13. #13
    Join Date
    January 2010
    Location
    Germany
    Posts
    29
    If there are any VB.Net programmers interested in this: I don't know how to use this project in VB.Net, if you want to use it you have to somehow transfer our work to VB.Net.
    Why is that? Assemblies are supposed to work with every .NET language.

  14. #14
    Join Date
    December 2009
    Location
    Deutschland
    Posts
    35
    As I've said, I don't know if the project works with VB.Net and if you can figure out how to, please post it here. I think you should be able to create the Plugin-Class in VB.Net easily, but I've never combined VB.Net and C# in one project.
    C# is much better then VB.Net anyway, so just use the C#-Version xP
    Last edited by addilind; October 4th, 2010 at 10:38 PM.

  15. #15
    Join Date
    December 2009
    Location
    Deutschland
    Posts
    35
    Code:
            public static ulong[] getChannelList(ulong serverConnectionHandlerID)
            {
                IntPtr result = IntPtr.Zero;
                if (TS3FunctionsDirect.getChannelList(serverConnectionHandlerID, ref result) != (uint)Errors.ERROR_ok)
                {
                    throw new Exception("TS3Functions.getChannelList returned an error");
                }
                List<ulong> tmp = new List<ulong>();
                int offset = 0;
                while (true)
                {
                    IntPtr i = Marshal.ReadIntPtr(result, offset);
                    offset += 8;
                    ushort e = (ushort)i;
                    TS3FunctionsDirect.freeMemory(i); // Is this the way it's supposed to be?
                    if (e == 0)
                        break;
                    else
                        tmp.Add(e);
                }
                return tmp.ToArray();
            }
    Take a look at TS3FunctionsDirect.freeMemory(i),
    this method works very well on an XP x86,
    but crashes on Windows 7 x64, both on x86 and x64 client.
    What goes wrong here? It should not be the offset, as this should be 8 Byte for long on 86 and 64 anyway
    Or do you need to free the referenced pointer?

    BTW: The whole works without the FreeMem
    Last edited by addilind; October 4th, 2010 at 10:41 PM.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. I need some help about Teamspeak 3 Service Wrapper
    By Barrybe in forum Tools / Web Based
    Replies: 11
    Last Post: June 2nd, 2016, 11:56 PM
  2. TS3 Service Wrapper reboots
    By frankbackes in forum Tools / Web Based
    Replies: 0
    Last Post: June 14th, 2014, 08:49 AM
  3. need Help with Teamspeak 3 Service Wrapper
    By Sir Lenny in forum Tools / Web Based
    Replies: 1
    Last Post: April 19th, 2013, 11:44 AM
  4. TS3 Service Wrapper Issue
    By tscritt in forum Client Plugins / Lua Scripts
    Replies: 3
    Last Post: January 10th, 2013, 12:46 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •